2 @message |
RecursionError: maximum recursion depth exceeded while calling a Python object
LOG DETAILS:
2025-07-02 06:41:16.110
2025-07-02 06:41:16.110 act = <firebird.qa.plugin.Action object at [hex]>
2025-07-02 06:41:16.110
2025-07-02 06:41:16.111 @pytest.mark.version('>=3')
2025-07-02 06:41:16.111 def test_1(act: Action):
2025-07-02 06:41:16.111 act.expected_stdout = expected_stdout
2025-07-02 06:41:16.111 act.execute()
2025-07-02 06:41:16.111 > assert act.clean_stdout == act.clean_expected_stdout
2025-07-02 06:41:16.111
2025-07-02 06:41:16.111 tests\bugs\core_2969_test.py:1211:
2025-07-02 06:41:16.111 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.111
2025-07-02 06:41:16.111 ops = ('==',), results = (False,)
2025-07-02 06:41:16.111 expls = ('%(py2)s\n{%(py2)s = %(py0)s.clean_stdout\n} == %(py6)s\n{%(py6)s = %(py4)s.clean_expected_stdout\n}',)
2025-07-02 06:41:16.111 each_obj = ('WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var...yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy')
2025-07-02 06:41:16.111
2025-07-02 06:41:16.111 def _call_reprcompare(
2025-07-02 06:41:16.111 ops: Sequence[str],
2025-07-02 06:41:16.111 results: Sequence[bool],
2025-07-02 06:41:16.111 expls: Sequence[str],
2025-07-02 06:41:16.111 each_obj: Sequence[object],
2025-07-02 06:41:16.111 ) -> str:
2025-07-02 06:41:16.111 for i, res, expl in zip(range(len(ops)), results, expls):
2025-07-02 06:41:16.112 try:
2025-07-02 06:41:16.112 done = not res
2025-07-02 06:41:16.112 except Exception:
2025-07-02 06:41:16.112 done = True
2025-07-02 06:41:16.112 if done:
2025-07-02 06:41:16.112 break
2025-07-02 06:41:16.112 if util._reprcompare is not None:
2025-07-02 06:41:16.112 > custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
2025-07-02 06:41:16.112
2025-07-02 06:41:16.112 C:\Python3x\Lib\site-packages\_pytest\assertion\rewrite.py:499:
2025-07-02 06:41:16.112 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.112
2025-07-02 06:41:16.112 op = '=='
2025-07-02 06:41:16.112 left = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var_... yyy\n1var_997 yyy\n1var_998 yyy\n1var_999 yyy'
2025-07-02 06:41:16.112 right = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'
2025-07-02 06:41:16.112
2025-07-02 06:41:16.112 def callbinrepr(op, left: object, right: object) -> Optional[str]:
2025-07-02 06:41:16.112 """Call the pytest_assertrepr_compare hook and prepare the result.
2025-07-02 06:41:16.113
2025-07-02 06:41:16.113 This uses the first result from the hook and then ensures the
2025-07-02 06:41:16.113 following:
2025-07-02 06:41:16.113 * Overly verbose explanations are truncated unless configured otherwise
2025-07-02 06:41:16.113 (eg. if running in verbose mode).
2025-07-02 06:41:16.113 * Embedded newlines are escaped to help util.format_explanation()
2025-07-02 06:41:16.113 later.
2025-07-02 06:41:16.113 * If the rewrite mode is used embedded %-characters are replaced
2025-07-02 06:41:16.113 to protect later % formatting.
2025-07-02 06:41:16.113
2025-07-02 06:41:16.113 The result can be formatted by util.format_explanation() for
2025-07-02 06:41:16.113 pretty printing.
2025-07-02 06:41:16.113 """
2025-07-02 06:41:16.113 > hook_result = ihook.pytest_assertrepr_compare(
2025-07-02 06:41:16.113 config=item.config, op=op, left=left, right=right
2025-07-02 06:41:16.113 )
2025-07-02 06:41:16.113
2025-07-02 06:41:16.113 C:\Python3x\Lib\site-packages\_pytest\assertion\__init__.py:141:
2025-07-02 06:41:16.113 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114 self = <HookCaller 'pytest_assertrepr_compare'>
2025-07-02 06:41:16.114 kwargs = {'config': <_pytest.config.Config object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY ...yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'}
2025-07-02 06:41:16.114 firstresult = False
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114 def __call__(self, **kwargs: object) -> Any:
2025-07-02 06:41:16.114 """Call the hook.
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114 Only accepts keyword arguments, which should match the hook
2025-07-02 06:41:16.114 specification.
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114 Returns the result(s) of calling all registered plugins, see
2025-07-02 06:41:16.114 :ref:`calling`.
2025-07-02 06:41:16.114 """
2025-07-02 06:41:16.114 assert (
2025-07-02 06:41:16.114 not self.is_historic()
2025-07-02 06:41:16.114 ), "Cannot directly call a historic hook - use call_historic instead."
2025-07-02 06:41:16.114 self._verify_all_args_are_provided(kwargs)
2025-07-02 06:41:16.114 firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
2025-07-02 06:41:16.114 # Copy because plugins may register other plugins during iteration (#438).
2025-07-02 06:41:16.115 > return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
2025-07-02 06:41:16.115
2025-07-02 06:41:16.115 C:\Python3x\Lib\site-packages\pluggy\_hooks.py:501:
2025-07-02 06:41:16.115 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.115
2025-07-02 06:41:16.115 self = <_pytest.config.PytestPluginManager object at [hex]>
2025-07-02 06:41:16.115 hook_name = 'pytest_assertrepr_compare'
2025-07-02 06:41:16.115 methods = [<HookImpl plugin_name='assertion', plugin=<module '_pytest.assertion' from 'C:\\Python3x\\Lib\\site-packages\\_pytest...plugin_name='firebird', plugin=<module 'firebird.qa.plugin' from 'H:\\QA\\firebird-qa\\src\\firebird\\qa\\plugin.py'>>]
2025-07-02 06:41:16.115 kwargs = {'config': <_pytest.config.Config object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY ...yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'}
2025-07-02 06:41:16.115 firstresult = False
2025-07-02 06:41:16.115
2025-07-02 06:41:16.115 def _hookexec(
2025-07-02 06:41:16.115 self,
2025-07-02 06:41:16.115 hook_name: str,
2025-07-02 06:41:16.115 methods: Sequence[HookImpl],
2025-07-02 06:41:16.115 kwargs: Mapping[str, object],
2025-07-02 06:41:16.115 firstresult: bool,
2025-07-02 06:41:16.115 ) -> object | list[object]:
2025-07-02 06:41:16.115 # called from all hookcaller instances.
2025-07-02 06:41:16.116 # enable_tracing will set its own wrapping function at self._inner_hookexec
2025-07-02 06:41:16.116 > return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116 C:\Python3x\Lib\site-packages\pluggy\_manager.py:119:
2025-07-02 06:41:16.116 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116 config = <_pytest.config.Config object at [hex]>, op = '=='
2025-07-02 06:41:16.116 left = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var_... yyy\n1var_997 yyy\n1var_998 yyy\n1var_999 yyy'
2025-07-02 06:41:16.116 right = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116 def pytest_assertrepr_compare(config: Config, op: str, left: object, right: object) -> Optional[List[str]]:
2025-07-02 06:41:16.116 """Returns explanation for comparisons in failing assert expressions.
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116 If both objects are `str`, uses `difflib.ndiff` to provide explanation.
2025-07-02 06:41:16.116 """
2025-07-02 06:41:16.116 if isinstance(left, str) and isinstance(right, str) and op == "==":
2025-07-02 06:41:16.116 # 16.11.2023, pzotov: we have to put empty string at the beginning of each comparing lists.
2025-07-02 06:41:16.116 # Otherwise first diff will be at the same line as 'assert' phrase, which causes readability be poor.
2025-07-02 06:41:16.116 #
2025-07-02 06:41:16.117 left_lines = ['']
2025-07-02 06:41:16.117 left_lines.extend(left.splitlines())
2025-07-02 06:41:16.117 right_lines = ['']
2025-07-02 06:41:16.117 right_lines.extend(right.splitlines())
2025-07-02 06:41:16.117
2025-07-02 06:41:16.117 # 16.11.2023, pzotov
2025-07-02 06:41:16.117 # ndiff output must be interpreted as following:
2025-07-02 06:41:16.117 # * "E - <some text>" ==> MISSED line (it was in EXPECTED text but absent in actual one).
2025-07-02 06:41:16.117 # * "E + <some_text>" ==> EXCESSIVE line (it is not in EXPECTED text but did appear in actual).
2025-07-02 06:41:16.117 # But for QA-purposes, this output must answer the question:
2025-07-02 06:41:16.117 # "what must be changed in ACTUAL output so that it became equal to EXPECTED"
2025-07-02 06:41:16.117 # (i.e. how to "REVERT" actual back to expected).
2025-07-02 06:41:16.117 # In order to see such result, we have to specify 'right_lines' to the 1st argument that is passed to ndiff().
2025-07-02 06:41:16.117 # ::: NB :::
2025-07-02 06:41:16.117 # We assume that all tests are written so that ACTUAL output is left side in 'assert' statement and EXPECTED
2025-07-02 06:41:16.117 # is right side, e.g: assert act.clean_stdout == act.clean_expected_stdout
2025-07-02 06:41:16.117 # This requirement is CRUCIAL if we use ndiff() instead of default pytest comparison method!
2025-07-02 06:41:16.117 #
2025-07-02 06:41:16.118 > return list(ndiff(right_lines, left_lines))
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118 src\firebird\qa\plugin.py:608:
2025-07-02 06:41:16.118 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.118 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.118 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118 def compare(self, a, b):
2025-07-02 06:41:16.118 r"""
2025-07-02 06:41:16.118 Compare two sequences of lines; generate the resulting delta.
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118 Each sequence must contain individual single-line strings ending with
2025-07-02 06:41:16.118 newlines. Such sequences can be obtained from the `readlines()` method
2025-07-02 06:41:16.118 of file-like objects. The delta generated also consists of newline-
2025-07-02 06:41:16.118 terminated strings, ready to be printed as-is via the writelines()
2025-07-02 06:41:16.118 method of a file-like object.
2025-07-02 06:41:16.118
2025-07-02 06:41:16.119 Example:
2025-07-02 06:41:16.119
2025-07-02 06:41:16.119 >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
2025-07-02 06:41:16.119 ... 'ore\ntree\nemu\n'.splitlines(True))),
2025-07-02 06:41:16.119 ... end="")
2025-07-02 06:41:16.119 - one
2025-07-02 06:41:16.119 + ore
2025-07-02 06:41:16.119 - two
2025-07-02 06:41:16.119 - three
2025-07-02 06:41:16.119 + tree
2025-07-02 06:41:16.119 + emu
2025-07-02 06:41:16.119 """
2025-07-02 06:41:16.119
2025-07-02 06:41:16.119 cruncher = SequenceMatcher(self.linejunk, a, b)
2025-07-02 06:41:16.119 for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
2025-07-02 06:41:16.119 if tag == 'replace':
2025-07-02 06:41:16.119 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.120 elif tag == 'delete':
2025-07-02 06:41:16.120 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.120 elif tag == 'insert':
2025-07-02 06:41:16.120 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.120 elif tag == 'equal':
2025-07-02 06:41:16.120 g = self._dump(' ', a, alo, ahi)
2025-07-02 06:41:16.120 else:
2025-07-02 06:41:16.120 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.120
2025-07-02 06:41:16.120 > yield from g
2025-07-02 06:41:16.120
2025-07-02 06:41:16.120 C:\Python3x\Lib\difflib.py:872:
2025-07-02 06:41:16.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.120
2025-07-02 06:41:16.120 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.120 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.120 alo = 3, ahi = 1101
2025-07-02 06:41:16.120 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.120 blo = 3, bhi = 1101
2025-07-02 06:41:16.121
2025-07-02 06:41:16.121 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.121 r"""
2025-07-02 06:41:16.121 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.121 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.121 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.121 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.121
2025-07-02 06:41:16.121 Example:
2025-07-02 06:41:16.121
2025-07-02 06:41:16.121 >>> d = Differ()
2025-07-02 06:41:16.121 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.121 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.121 >>> print(''.join(results), end="")
2025-07-02 06:41:16.121 - abcDefghiJkl
2025-07-02 06:41:16.121 + abcdefGhijkl
2025-07-02 06:41:16.121 """
2025-07-02 06:41:16.121
2025-07-02 06:41:16.122 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.122 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.122 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.122 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.122 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.122
2025-07-02 06:41:16.122 # search for the pair that matches best without being identical
2025-07-02 06:41:16.122 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.122 # on junk -- unless we have to)
2025-07-02 06:41:16.122 for j in range(blo, bhi):
2025-07-02 06:41:16.122 bj = b[j]
2025-07-02 06:41:16.122 cruncher.set_seq2(bj)
2025-07-02 06:41:16.122 for i in range(alo, ahi):
2025-07-02 06:41:16.122 ai = a[i]
2025-07-02 06:41:16.122 if ai == bj:
2025-07-02 06:41:16.122 if eqi is None:
2025-07-02 06:41:16.122 eqi, eqj = i, j
2025-07-02 06:41:16.122 continue
2025-07-02 06:41:16.122 cruncher.set_seq1(ai)
2025-07-02 06:41:16.122 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.123 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.123 # compares by a factor of 3.
2025-07-02 06:41:16.123 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.123 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.123 # of the computation is cached by cruncher
2025-07-02 06:41:16.123 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.123 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.123 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.123 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.123 if best_ratio < cutoff:
2025-07-02 06:41:16.123 # no non-identical "pretty close" pair
2025-07-02 06:41:16.123 if eqi is None:
2025-07-02 06:41:16.123 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.123 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.123 return
2025-07-02 06:41:16.123 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.123 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.123 else:
2025-07-02 06:41:16.123 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.123 eqi = None
2025-07-02 06:41:16.124
2025-07-02 06:41:16.124 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.124 # identical
2025-07-02 06:41:16.124
2025-07-02 06:41:16.124 # pump out diffs from before the synch point
2025-07-02 06:41:16.124 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.124
2025-07-02 06:41:16.124 # do intraline marking on the synch pair
2025-07-02 06:41:16.124 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.124 if eqi is None:
2025-07-02 06:41:16.124 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.124 atags = btags = ""
2025-07-02 06:41:16.124 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.124 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.124 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.124 if tag == 'replace':
2025-07-02 06:41:16.124 atags += '^' * la
2025-07-02 06:41:16.124 btags += '^' * lb
2025-07-02 06:41:16.124 elif tag == 'delete':
2025-07-02 06:41:16.124 atags += '-' * la
2025-07-02 06:41:16.125 elif tag == 'insert':
2025-07-02 06:41:16.125 btags += '+' * lb
2025-07-02 06:41:16.125 elif tag == 'equal':
2025-07-02 06:41:16.125 atags += ' ' * la
2025-07-02 06:41:16.125 btags += ' ' * lb
2025-07-02 06:41:16.125 else:
2025-07-02 06:41:16.125 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.125 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.125 else:
2025-07-02 06:41:16.125 # the synch pair is identical
2025-07-02 06:41:16.125 yield ' ' + aelt
2025-07-02 06:41:16.125
2025-07-02 06:41:16.125 # pump out diffs from after the synch point
2025-07-02 06:41:16.125 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.125
2025-07-02 06:41:16.125 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.125 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.125
2025-07-02 06:41:16.125 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.125 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.126 alo = 4, ahi = 1101
2025-07-02 06:41:16.126 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.126 blo = 4, bhi = 1101
2025-07-02 06:41:16.126
2025-07-02 06:41:16.126 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.126 g = []
2025-07-02 06:41:16.126 if alo < ahi:
2025-07-02 06:41:16.126 if blo < bhi:
2025-07-02 06:41:16.126 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.126 else:
2025-07-02 06:41:16.126 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.126 elif blo < bhi:
2025-07-02 06:41:16.126 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.126
2025-07-02 06:41:16.126 > yield from g
2025-07-02 06:41:16.126
2025-07-02 06:41:16.126 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.126 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.127 alo = 4, ahi = 1101
2025-07-02 06:41:16.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.127 blo = 4, bhi = 1101
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.127 r"""
2025-07-02 06:41:16.127 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.127 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.127 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.127 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127 Example:
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127 >>> d = Differ()
2025-07-02 06:41:16.127 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.127 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.128 >>> print(''.join(results), end="")
2025-07-02 06:41:16.128 - abcDefghiJkl
2025-07-02 06:41:16.128 + abcdefGhijkl
2025-07-02 06:41:16.128 """
2025-07-02 06:41:16.128
2025-07-02 06:41:16.128 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.128 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.128 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.128 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.128 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.128
2025-07-02 06:41:16.128 # search for the pair that matches best without being identical
2025-07-02 06:41:16.128 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.128 # on junk -- unless we have to)
2025-07-02 06:41:16.128 for j in range(blo, bhi):
2025-07-02 06:41:16.128 bj = b[j]
2025-07-02 06:41:16.129 cruncher.set_seq2(bj)
2025-07-02 06:41:16.129 for i in range(alo, ahi):
2025-07-02 06:41:16.129 ai = a[i]
2025-07-02 06:41:16.129 if ai == bj:
2025-07-02 06:41:16.129 if eqi is None:
2025-07-02 06:41:16.129 eqi, eqj = i, j
2025-07-02 06:41:16.129 continue
2025-07-02 06:41:16.129 cruncher.set_seq1(ai)
2025-07-02 06:41:16.129 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.129 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.129 # compares by a factor of 3.
2025-07-02 06:41:16.129 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.129 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.129 # of the computation is cached by cruncher
2025-07-02 06:41:16.129 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.129 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.129 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.129 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.129 if best_ratio < cutoff:
2025-07-02 06:41:16.130 # no non-identical "pretty close" pair
2025-07-02 06:41:16.130 if eqi is None:
2025-07-02 06:41:16.130 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.130 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.130 return
2025-07-02 06:41:16.130 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.130 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.130 else:
2025-07-02 06:41:16.130 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.130 eqi = None
2025-07-02 06:41:16.130
2025-07-02 06:41:16.130 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.130 # identical
2025-07-02 06:41:16.130
2025-07-02 06:41:16.130 # pump out diffs from before the synch point
2025-07-02 06:41:16.130 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.130
2025-07-02 06:41:16.130 # do intraline marking on the synch pair
2025-07-02 06:41:16.130 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.130 if eqi is None:
2025-07-02 06:41:16.130 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.131 atags = btags = ""
2025-07-02 06:41:16.131 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.131 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.131 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.131 if tag == 'replace':
2025-07-02 06:41:16.131 atags += '^' * la
2025-07-02 06:41:16.131 btags += '^' * lb
2025-07-02 06:41:16.131 elif tag == 'delete':
2025-07-02 06:41:16.131 atags += '-' * la
2025-07-02 06:41:16.131 elif tag == 'insert':
2025-07-02 06:41:16.131 btags += '+' * lb
2025-07-02 06:41:16.131 elif tag == 'equal':
2025-07-02 06:41:16.131 atags += ' ' * la
2025-07-02 06:41:16.131 btags += ' ' * lb
2025-07-02 06:41:16.131 else:
2025-07-02 06:41:16.131 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.131 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.131 else:
2025-07-02 06:41:16.131 # the synch pair is identical
2025-07-02 06:41:16.131 yield ' ' + aelt
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132 # pump out diffs from after the synch point
2025-07-02 06:41:16.132 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.132 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.132 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.132 alo = 5, ahi = 1101
2025-07-02 06:41:16.132 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.132 blo = 5, bhi = 1101
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.132 g = []
2025-07-02 06:41:16.132 if alo < ahi:
2025-07-02 06:41:16.132 if blo < bhi:
2025-07-02 06:41:16.132 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.132 else:
2025-07-02 06:41:16.132 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.133 elif blo < bhi:
2025-07-02 06:41:16.133 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 > yield from g
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.133 alo = 5, ahi = 1101
2025-07-02 06:41:16.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.133 blo = 5, bhi = 1101
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.133 r"""
2025-07-02 06:41:16.133 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.133 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.133 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.133 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134 Example:
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134 >>> d = Differ()
2025-07-02 06:41:16.134 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.134 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.134 >>> print(''.join(results), end="")
2025-07-02 06:41:16.134 - abcDefghiJkl
2025-07-02 06:41:16.134 + abcdefGhijkl
2025-07-02 06:41:16.134 """
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.134 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.134 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.134 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.134 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134 # search for the pair that matches best without being identical
2025-07-02 06:41:16.135 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.135 # on junk -- unless we have to)
2025-07-02 06:41:16.135 for j in range(blo, bhi):
2025-07-02 06:41:16.135 bj = b[j]
2025-07-02 06:41:16.135 cruncher.set_seq2(bj)
2025-07-02 06:41:16.135 for i in range(alo, ahi):
2025-07-02 06:41:16.135 ai = a[i]
2025-07-02 06:41:16.135 if ai == bj:
2025-07-02 06:41:16.135 if eqi is None:
2025-07-02 06:41:16.135 eqi, eqj = i, j
2025-07-02 06:41:16.135 continue
2025-07-02 06:41:16.135 cruncher.set_seq1(ai)
2025-07-02 06:41:16.135 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.135 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.135 # compares by a factor of 3.
2025-07-02 06:41:16.135 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.135 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.135 # of the computation is cached by cruncher
2025-07-02 06:41:16.135 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.136 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.136 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.136 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.136 if best_ratio < cutoff:
2025-07-02 06:41:16.136 # no non-identical "pretty close" pair
2025-07-02 06:41:16.136 if eqi is None:
2025-07-02 06:41:16.136 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.136 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.136 return
2025-07-02 06:41:16.136 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.136 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.136 else:
2025-07-02 06:41:16.136 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.136 eqi = None
2025-07-02 06:41:16.136
2025-07-02 06:41:16.136 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.136 # identical
2025-07-02 06:41:16.136
2025-07-02 06:41:16.136 # pump out diffs from before the synch point
2025-07-02 06:41:16.136 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.137
2025-07-02 06:41:16.137 # do intraline marking on the synch pair
2025-07-02 06:41:16.137 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.137 if eqi is None:
2025-07-02 06:41:16.137 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.137 atags = btags = ""
2025-07-02 06:41:16.137 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.137 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.137 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.137 if tag == 'replace':
2025-07-02 06:41:16.137 atags += '^' * la
2025-07-02 06:41:16.137 btags += '^' * lb
2025-07-02 06:41:16.137 elif tag == 'delete':
2025-07-02 06:41:16.137 atags += '-' * la
2025-07-02 06:41:16.137 elif tag == 'insert':
2025-07-02 06:41:16.137 btags += '+' * lb
2025-07-02 06:41:16.137 elif tag == 'equal':
2025-07-02 06:41:16.137 atags += ' ' * la
2025-07-02 06:41:16.137 btags += ' ' * lb
2025-07-02 06:41:16.137 else:
2025-07-02 06:41:16.138 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.138 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.138 else:
2025-07-02 06:41:16.138 # the synch pair is identical
2025-07-02 06:41:16.138 yield ' ' + aelt
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138 # pump out diffs from after the synch point
2025-07-02 06:41:16.138 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.138 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.138 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.138 alo = 6, ahi = 1101
2025-07-02 06:41:16.138 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.138 blo = 6, bhi = 1101
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.138 g = []
2025-07-02 06:41:16.139 if alo < ahi:
2025-07-02 06:41:16.139 if blo < bhi:
2025-07-02 06:41:16.139 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.139 else:
2025-07-02 06:41:16.139 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.139 elif blo < bhi:
2025-07-02 06:41:16.139 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 > yield from g
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.139 alo = 6, ahi = 1101
2025-07-02 06:41:16.139 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.139 blo = 6, bhi = 1101
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.140 r"""
2025-07-02 06:41:16.140 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.140 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.140 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.140 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.140
2025-07-02 06:41:16.140 Example:
2025-07-02 06:41:16.140
2025-07-02 06:41:16.140 >>> d = Differ()
2025-07-02 06:41:16.140 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.140 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.140 >>> print(''.join(results), end="")
2025-07-02 06:41:16.140 - abcDefghiJkl
2025-07-02 06:41:16.140 + abcdefGhijkl
2025-07-02 06:41:16.140 """
2025-07-02 06:41:16.140
2025-07-02 06:41:16.140 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.140 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.140 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.141 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.141 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.141
2025-07-02 06:41:16.141 # search for the pair that matches best without being identical
2025-07-02 06:41:16.141 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.141 # on junk -- unless we have to)
2025-07-02 06:41:16.141 for j in range(blo, bhi):
2025-07-02 06:41:16.141 bj = b[j]
2025-07-02 06:41:16.141 cruncher.set_seq2(bj)
2025-07-02 06:41:16.141 for i in range(alo, ahi):
2025-07-02 06:41:16.141 ai = a[i]
2025-07-02 06:41:16.141 if ai == bj:
2025-07-02 06:41:16.141 if eqi is None:
2025-07-02 06:41:16.141 eqi, eqj = i, j
2025-07-02 06:41:16.141 continue
2025-07-02 06:41:16.141 cruncher.set_seq1(ai)
2025-07-02 06:41:16.141 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.141 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.141 # compares by a factor of 3.
2025-07-02 06:41:16.141 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.142 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.142 # of the computation is cached by cruncher
2025-07-02 06:41:16.142 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.142 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.142 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.142 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.142 if best_ratio < cutoff:
2025-07-02 06:41:16.142 # no non-identical "pretty close" pair
2025-07-02 06:41:16.142 if eqi is None:
2025-07-02 06:41:16.142 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.142 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.142 return
2025-07-02 06:41:16.142 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.142 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.142 else:
2025-07-02 06:41:16.142 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.142 eqi = None
2025-07-02 06:41:16.142
2025-07-02 06:41:16.142 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.143 # identical
2025-07-02 06:41:16.143
2025-07-02 06:41:16.143 # pump out diffs from before the synch point
2025-07-02 06:41:16.143 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.143
2025-07-02 06:41:16.143 # do intraline marking on the synch pair
2025-07-02 06:41:16.143 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.143 if eqi is None:
2025-07-02 06:41:16.143 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.143 atags = btags = ""
2025-07-02 06:41:16.143 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.143 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.143 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.143 if tag == 'replace':
2025-07-02 06:41:16.143 atags += '^' * la
2025-07-02 06:41:16.143 btags += '^' * lb
2025-07-02 06:41:16.143 elif tag == 'delete':
2025-07-02 06:41:16.143 atags += '-' * la
2025-07-02 06:41:16.143 elif tag == 'insert':
2025-07-02 06:41:16.144 btags += '+' * lb
2025-07-02 06:41:16.144 elif tag == 'equal':
2025-07-02 06:41:16.144 atags += ' ' * la
2025-07-02 06:41:16.144 btags += ' ' * lb
2025-07-02 06:41:16.144 else:
2025-07-02 06:41:16.144 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.144 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.144 else:
2025-07-02 06:41:16.144 # the synch pair is identical
2025-07-02 06:41:16.144 yield ' ' + aelt
2025-07-02 06:41:16.144
2025-07-02 06:41:16.144 # pump out diffs from after the synch point
2025-07-02 06:41:16.144 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.144
2025-07-02 06:41:16.144 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.144 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.144
2025-07-02 06:41:16.144 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.144 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.145 alo = 7, ahi = 1101
2025-07-02 06:41:16.145 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.145 blo = 7, bhi = 1101
2025-07-02 06:41:16.145
2025-07-02 06:41:16.145 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.145 g = []
2025-07-02 06:41:16.145 if alo < ahi:
2025-07-02 06:41:16.145 if blo < bhi:
2025-07-02 06:41:16.145 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.145 else:
2025-07-02 06:41:16.145 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.145 elif blo < bhi:
2025-07-02 06:41:16.145 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.145
2025-07-02 06:41:16.145 > yield from g
2025-07-02 06:41:16.145
2025-07-02 06:41:16.145 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.145 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.145
2025-07-02 06:41:16.146 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.146 alo = 7, ahi = 1101
2025-07-02 06:41:16.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.146 blo = 7, bhi = 1101
2025-07-02 06:41:16.146
2025-07-02 06:41:16.146 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.146 r"""
2025-07-02 06:41:16.146 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.146 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.146 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.146 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.146
2025-07-02 06:41:16.146 Example:
2025-07-02 06:41:16.146
2025-07-02 06:41:16.146 >>> d = Differ()
2025-07-02 06:41:16.146 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.146 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.146 >>> print(''.join(results), end="")
2025-07-02 06:41:16.146 - abcDefghiJkl
2025-07-02 06:41:16.147 + abcdefGhijkl
2025-07-02 06:41:16.147 """
2025-07-02 06:41:16.147
2025-07-02 06:41:16.147 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.147 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.147 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.147 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.147 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.147
2025-07-02 06:41:16.147 # search for the pair that matches best without being identical
2025-07-02 06:41:16.147 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.147 # on junk -- unless we have to)
2025-07-02 06:41:16.147 for j in range(blo, bhi):
2025-07-02 06:41:16.147 bj = b[j]
2025-07-02 06:41:16.147 cruncher.set_seq2(bj)
2025-07-02 06:41:16.147 for i in range(alo, ahi):
2025-07-02 06:41:16.147 ai = a[i]
2025-07-02 06:41:16.147 if ai == bj:
2025-07-02 06:41:16.147 if eqi is None:
2025-07-02 06:41:16.148 eqi, eqj = i, j
2025-07-02 06:41:16.148 continue
2025-07-02 06:41:16.148 cruncher.set_seq1(ai)
2025-07-02 06:41:16.148 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.148 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.148 # compares by a factor of 3.
2025-07-02 06:41:16.148 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.148 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.148 # of the computation is cached by cruncher
2025-07-02 06:41:16.148 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.148 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.148 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.148 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.148 if best_ratio < cutoff:
2025-07-02 06:41:16.148 # no non-identical "pretty close" pair
2025-07-02 06:41:16.148 if eqi is None:
2025-07-02 06:41:16.148 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.148 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.148 return
2025-07-02 06:41:16.148 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.149 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.149 else:
2025-07-02 06:41:16.149 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.149 eqi = None
2025-07-02 06:41:16.149
2025-07-02 06:41:16.149 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.149 # identical
2025-07-02 06:41:16.149
2025-07-02 06:41:16.149 # pump out diffs from before the synch point
2025-07-02 06:41:16.149 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.149
2025-07-02 06:41:16.149 # do intraline marking on the synch pair
2025-07-02 06:41:16.149 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.149 if eqi is None:
2025-07-02 06:41:16.149 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.149 atags = btags = ""
2025-07-02 06:41:16.149 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.149 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.149 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.149 if tag == 'replace':
2025-07-02 06:41:16.150 atags += '^' * la
2025-07-02 06:41:16.150 btags += '^' * lb
2025-07-02 06:41:16.150 elif tag == 'delete':
2025-07-02 06:41:16.150 atags += '-' * la
2025-07-02 06:41:16.150 elif tag == 'insert':
2025-07-02 06:41:16.150 btags += '+' * lb
2025-07-02 06:41:16.150 elif tag == 'equal':
2025-07-02 06:41:16.150 atags += ' ' * la
2025-07-02 06:41:16.150 btags += ' ' * lb
2025-07-02 06:41:16.150 else:
2025-07-02 06:41:16.150 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.150 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.150 else:
2025-07-02 06:41:16.150 # the synch pair is identical
2025-07-02 06:41:16.150 yield ' ' + aelt
2025-07-02 06:41:16.150
2025-07-02 06:41:16.150 # pump out diffs from after the synch point
2025-07-02 06:41:16.150 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.150
2025-07-02 06:41:16.150 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.150 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.151 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.151 alo = 8, ahi = 1101
2025-07-02 06:41:16.151 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.151 blo = 8, bhi = 1101
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.151 g = []
2025-07-02 06:41:16.151 if alo < ahi:
2025-07-02 06:41:16.151 if blo < bhi:
2025-07-02 06:41:16.151 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.151 else:
2025-07-02 06:41:16.151 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.151 elif blo < bhi:
2025-07-02 06:41:16.151 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 > yield from g
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.152 alo = 8, ahi = 1101
2025-07-02 06:41:16.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.152 blo = 8, bhi = 1101
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.152 r"""
2025-07-02 06:41:16.152 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.152 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.152 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.152 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152 Example:
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152 >>> d = Differ()
2025-07-02 06:41:16.153 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.153 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.153 >>> print(''.join(results), end="")
2025-07-02 06:41:16.153 - abcDefghiJkl
2025-07-02 06:41:16.153 + abcdefGhijkl
2025-07-02 06:41:16.153 """
2025-07-02 06:41:16.153
2025-07-02 06:41:16.153 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.153 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.153 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.153 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.153 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.153
2025-07-02 06:41:16.153 # search for the pair that matches best without being identical
2025-07-02 06:41:16.153 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.153 # on junk -- unless we have to)
2025-07-02 06:41:16.153 for j in range(blo, bhi):
2025-07-02 06:41:16.154 bj = b[j]
2025-07-02 06:41:16.154 cruncher.set_seq2(bj)
2025-07-02 06:41:16.154 for i in range(alo, ahi):
2025-07-02 06:41:16.154 ai = a[i]
2025-07-02 06:41:16.154 if ai == bj:
2025-07-02 06:41:16.154 if eqi is None:
2025-07-02 06:41:16.154 eqi, eqj = i, j
2025-07-02 06:41:16.154 continue
2025-07-02 06:41:16.154 cruncher.set_seq1(ai)
2025-07-02 06:41:16.154 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.154 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.154 # compares by a factor of 3.
2025-07-02 06:41:16.154 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.154 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.154 # of the computation is cached by cruncher
2025-07-02 06:41:16.154 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.154 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.154 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.154 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.155 if best_ratio < cutoff:
2025-07-02 06:41:16.155 # no non-identical "pretty close" pair
2025-07-02 06:41:16.155 if eqi is None:
2025-07-02 06:41:16.155 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.155 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.155 return
2025-07-02 06:41:16.155 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.155 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.155 else:
2025-07-02 06:41:16.155 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.155 eqi = None
2025-07-02 06:41:16.155
2025-07-02 06:41:16.155 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.155 # identical
2025-07-02 06:41:16.155
2025-07-02 06:41:16.155 # pump out diffs from before the synch point
2025-07-02 06:41:16.155 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.155
2025-07-02 06:41:16.155 # do intraline marking on the synch pair
2025-07-02 06:41:16.155 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.156 if eqi is None:
2025-07-02 06:41:16.156 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.156 atags = btags = ""
2025-07-02 06:41:16.156 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.156 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.156 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.156 if tag == 'replace':
2025-07-02 06:41:16.156 atags += '^' * la
2025-07-02 06:41:16.156 btags += '^' * lb
2025-07-02 06:41:16.156 elif tag == 'delete':
2025-07-02 06:41:16.156 atags += '-' * la
2025-07-02 06:41:16.156 elif tag == 'insert':
2025-07-02 06:41:16.156 btags += '+' * lb
2025-07-02 06:41:16.156 elif tag == 'equal':
2025-07-02 06:41:16.156 atags += ' ' * la
2025-07-02 06:41:16.156 btags += ' ' * lb
2025-07-02 06:41:16.156 else:
2025-07-02 06:41:16.156 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.156 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.156 else:
2025-07-02 06:41:16.157 # the synch pair is identical
2025-07-02 06:41:16.157 yield ' ' + aelt
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157 # pump out diffs from after the synch point
2025-07-02 06:41:16.157 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.157 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.157 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.157 alo = 9, ahi = 1101
2025-07-02 06:41:16.157 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.157 blo = 9, bhi = 1101
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.157 g = []
2025-07-02 06:41:16.157 if alo < ahi:
2025-07-02 06:41:16.157 if blo < bhi:
2025-07-02 06:41:16.158 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.158 else:
2025-07-02 06:41:16.158 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.158 elif blo < bhi:
2025-07-02 06:41:16.158 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 > yield from g
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.158 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.158 alo = 9, ahi = 1101
2025-07-02 06:41:16.158 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.158 blo = 9, bhi = 1101
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.158 r"""
2025-07-02 06:41:16.158 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.159 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.159 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.159 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.159
2025-07-02 06:41:16.159 Example:
2025-07-02 06:41:16.159
2025-07-02 06:41:16.159 >>> d = Differ()
2025-07-02 06:41:16.159 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.159 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.159 >>> print(''.join(results), end="")
2025-07-02 06:41:16.159 - abcDefghiJkl
2025-07-02 06:41:16.159 + abcdefGhijkl
2025-07-02 06:41:16.159 """
2025-07-02 06:41:16.159
2025-07-02 06:41:16.159 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.159 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.159 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.160 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.160 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.160
2025-07-02 06:41:16.160 # search for the pair that matches best without being identical
2025-07-02 06:41:16.160 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.160 # on junk -- unless we have to)
2025-07-02 06:41:16.160 for j in range(blo, bhi):
2025-07-02 06:41:16.160 bj = b[j]
2025-07-02 06:41:16.160 cruncher.set_seq2(bj)
2025-07-02 06:41:16.160 for i in range(alo, ahi):
2025-07-02 06:41:16.160 ai = a[i]
2025-07-02 06:41:16.160 if ai == bj:
2025-07-02 06:41:16.160 if eqi is None:
2025-07-02 06:41:16.160 eqi, eqj = i, j
2025-07-02 06:41:16.160 continue
2025-07-02 06:41:16.160 cruncher.set_seq1(ai)
2025-07-02 06:41:16.160 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.160 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.160 # compares by a factor of 3.
2025-07-02 06:41:16.161 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.161 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.161 # of the computation is cached by cruncher
2025-07-02 06:41:16.161 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.161 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.161 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.161 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.161 if best_ratio < cutoff:
2025-07-02 06:41:16.161 # no non-identical "pretty close" pair
2025-07-02 06:41:16.161 if eqi is None:
2025-07-02 06:41:16.161 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.161 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.161 return
2025-07-02 06:41:16.161 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.161 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.161 else:
2025-07-02 06:41:16.161 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.161 eqi = None
2025-07-02 06:41:16.162
2025-07-02 06:41:16.162 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.162 # identical
2025-07-02 06:41:16.162
2025-07-02 06:41:16.162 # pump out diffs from before the synch point
2025-07-02 06:41:16.162 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.162
2025-07-02 06:41:16.162 # do intraline marking on the synch pair
2025-07-02 06:41:16.162 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.162 if eqi is None:
2025-07-02 06:41:16.162 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.162 atags = btags = ""
2025-07-02 06:41:16.162 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.162 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.162 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.162 if tag == 'replace':
2025-07-02 06:41:16.162 atags += '^' * la
2025-07-02 06:41:16.162 btags += '^' * lb
2025-07-02 06:41:16.162 elif tag == 'delete':
2025-07-02 06:41:16.162 atags += '-' * la
2025-07-02 06:41:16.163 elif tag == 'insert':
2025-07-02 06:41:16.163 btags += '+' * lb
2025-07-02 06:41:16.163 elif tag == 'equal':
2025-07-02 06:41:16.163 atags += ' ' * la
2025-07-02 06:41:16.163 btags += ' ' * lb
2025-07-02 06:41:16.163 else:
2025-07-02 06:41:16.163 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.163 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.163 else:
2025-07-02 06:41:16.163 # the synch pair is identical
2025-07-02 06:41:16.163 yield ' ' + aelt
2025-07-02 06:41:16.163
2025-07-02 06:41:16.163 # pump out diffs from after the synch point
2025-07-02 06:41:16.163 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.163
2025-07-02 06:41:16.163 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.163 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.163
2025-07-02 06:41:16.163 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.163 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.164 alo = 10, ahi = 1101
2025-07-02 06:41:16.164 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.164 blo = 10, bhi = 1101
2025-07-02 06:41:16.164
2025-07-02 06:41:16.164 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.164 g = []
2025-07-02 06:41:16.164 if alo < ahi:
2025-07-02 06:41:16.164 if blo < bhi:
2025-07-02 06:41:16.164 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.164 else:
2025-07-02 06:41:16.164 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.164 elif blo < bhi:
2025-07-02 06:41:16.164 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.164
2025-07-02 06:41:16.164 > yield from g
2025-07-02 06:41:16.164
2025-07-02 06:41:16.164 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.164 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.164
2025-07-02 06:41:16.165 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.165 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.165 alo = 10, ahi = 1101
2025-07-02 06:41:16.165 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.165 blo = 10, bhi = 1101
2025-07-02 06:41:16.165
2025-07-02 06:41:16.165 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.165 r"""
2025-07-02 06:41:16.165 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.165 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.165 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.165 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.165
2025-07-02 06:41:16.165 Example:
2025-07-02 06:41:16.165
2025-07-02 06:41:16.165 >>> d = Differ()
2025-07-02 06:41:16.165 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.165 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.165 >>> print(''.join(results), end="")
2025-07-02 06:41:16.166 - abcDefghiJkl
2025-07-02 06:41:16.166 + abcdefGhijkl
2025-07-02 06:41:16.166 """
2025-07-02 06:41:16.166
2025-07-02 06:41:16.166 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.166 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.166 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.166 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.166 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.166
2025-07-02 06:41:16.166 # search for the pair that matches best without being identical
2025-07-02 06:41:16.166 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.166 # on junk -- unless we have to)
2025-07-02 06:41:16.166 for j in range(blo, bhi):
2025-07-02 06:41:16.166 bj = b[j]
2025-07-02 06:41:16.166 cruncher.set_seq2(bj)
2025-07-02 06:41:16.166 for i in range(alo, ahi):
2025-07-02 06:41:16.166 ai = a[i]
2025-07-02 06:41:16.167 if ai == bj:
2025-07-02 06:41:16.167 if eqi is None:
2025-07-02 06:41:16.167 eqi, eqj = i, j
2025-07-02 06:41:16.167 continue
2025-07-02 06:41:16.167 cruncher.set_seq1(ai)
2025-07-02 06:41:16.167 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.167 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.167 # compares by a factor of 3.
2025-07-02 06:41:16.167 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.167 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.167 # of the computation is cached by cruncher
2025-07-02 06:41:16.167 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.167 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.167 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.167 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.167 if best_ratio < cutoff:
2025-07-02 06:41:16.167 # no non-identical "pretty close" pair
2025-07-02 06:41:16.167 if eqi is None:
2025-07-02 06:41:16.167 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.167 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.168 return
2025-07-02 06:41:16.168 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.168 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.168 else:
2025-07-02 06:41:16.168 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.168 eqi = None
2025-07-02 06:41:16.168
2025-07-02 06:41:16.168 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.168 # identical
2025-07-02 06:41:16.168
2025-07-02 06:41:16.168 # pump out diffs from before the synch point
2025-07-02 06:41:16.168 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.168
2025-07-02 06:41:16.168 # do intraline marking on the synch pair
2025-07-02 06:41:16.168 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.168 if eqi is None:
2025-07-02 06:41:16.168 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.168 atags = btags = ""
2025-07-02 06:41:16.168 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.169 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.169 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.169 if tag == 'replace':
2025-07-02 06:41:16.169 atags += '^' * la
2025-07-02 06:41:16.169 btags += '^' * lb
2025-07-02 06:41:16.169 elif tag == 'delete':
2025-07-02 06:41:16.169 atags += '-' * la
2025-07-02 06:41:16.169 elif tag == 'insert':
2025-07-02 06:41:16.169 btags += '+' * lb
2025-07-02 06:41:16.169 elif tag == 'equal':
2025-07-02 06:41:16.169 atags += ' ' * la
2025-07-02 06:41:16.169 btags += ' ' * lb
2025-07-02 06:41:16.169 else:
2025-07-02 06:41:16.169 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.169 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.169 else:
2025-07-02 06:41:16.169 # the synch pair is identical
2025-07-02 06:41:16.169 yield ' ' + aelt
2025-07-02 06:41:16.169
2025-07-02 06:41:16.169 # pump out diffs from after the synch point
2025-07-02 06:41:16.170 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.170
2025-07-02 06:41:16.170 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.170 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.170
2025-07-02 06:41:16.170 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.170 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.170 alo = 11, ahi = 1101
2025-07-02 06:41:16.170 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.170 blo = 11, bhi = 1101
2025-07-02 06:41:16.170
2025-07-02 06:41:16.170 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.170 g = []
2025-07-02 06:41:16.170 if alo < ahi:
2025-07-02 06:41:16.170 if blo < bhi:
2025-07-02 06:41:16.170 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.170 else:
2025-07-02 06:41:16.170 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.171 elif blo < bhi:
2025-07-02 06:41:16.171 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 > yield from g
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.171 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.171 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.171 alo = 11, ahi = 1101
2025-07-02 06:41:16.171 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.171 blo = 11, bhi = 1101
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.171 r"""
2025-07-02 06:41:16.171 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.171 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.171 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.172 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.172
2025-07-02 06:41:16.172 Example:
2025-07-02 06:41:16.172
2025-07-02 06:41:16.172 >>> d = Differ()
2025-07-02 06:41:16.172 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.172 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.172 >>> print(''.join(results), end="")
2025-07-02 06:41:16.172 - abcDefghiJkl
2025-07-02 06:41:16.172 + abcdefGhijkl
2025-07-02 06:41:16.172 """
2025-07-02 06:41:16.172
2025-07-02 06:41:16.172 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.172 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.172 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.172 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.172 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.172
2025-07-02 06:41:16.173 # search for the pair that matches best without being identical
2025-07-02 06:41:16.173 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.173 # on junk -- unless we have to)
2025-07-02 06:41:16.173 for j in range(blo, bhi):
2025-07-02 06:41:16.173 bj = b[j]
2025-07-02 06:41:16.173 cruncher.set_seq2(bj)
2025-07-02 06:41:16.173 for i in range(alo, ahi):
2025-07-02 06:41:16.173 ai = a[i]
2025-07-02 06:41:16.173 if ai == bj:
2025-07-02 06:41:16.173 if eqi is None:
2025-07-02 06:41:16.173 eqi, eqj = i, j
2025-07-02 06:41:16.173 continue
2025-07-02 06:41:16.173 cruncher.set_seq1(ai)
2025-07-02 06:41:16.173 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.173 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.173 # compares by a factor of 3.
2025-07-02 06:41:16.173 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.173 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.173 # of the computation is cached by cruncher
2025-07-02 06:41:16.173 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.174 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.174 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.174 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.174 if best_ratio < cutoff:
2025-07-02 06:41:16.174 # no non-identical "pretty close" pair
2025-07-02 06:41:16.174 if eqi is None:
2025-07-02 06:41:16.174 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.174 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.174 return
2025-07-02 06:41:16.174 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.174 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.174 else:
2025-07-02 06:41:16.174 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.174 eqi = None
2025-07-02 06:41:16.174
2025-07-02 06:41:16.174 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.174 # identical
2025-07-02 06:41:16.174
2025-07-02 06:41:16.174 # pump out diffs from before the synch point
2025-07-02 06:41:16.175 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.175
2025-07-02 06:41:16.175 # do intraline marking on the synch pair
2025-07-02 06:41:16.175 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.175 if eqi is None:
2025-07-02 06:41:16.175 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.175 atags = btags = ""
2025-07-02 06:41:16.175 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.175 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.175 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.175 if tag == 'replace':
2025-07-02 06:41:16.175 atags += '^' * la
2025-07-02 06:41:16.175 btags += '^' * lb
2025-07-02 06:41:16.175 elif tag == 'delete':
2025-07-02 06:41:16.175 atags += '-' * la
2025-07-02 06:41:16.175 elif tag == 'insert':
2025-07-02 06:41:16.175 btags += '+' * lb
2025-07-02 06:41:16.175 elif tag == 'equal':
2025-07-02 06:41:16.175 atags += ' ' * la
2025-07-02 06:41:16.175 btags += ' ' * lb
2025-07-02 06:41:16.176 else:
2025-07-02 06:41:16.176 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.176 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.176 else:
2025-07-02 06:41:16.176 # the synch pair is identical
2025-07-02 06:41:16.176 yield ' ' + aelt
2025-07-02 06:41:16.176
2025-07-02 06:41:16.176 # pump out diffs from after the synch point
2025-07-02 06:41:16.176 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.176
2025-07-02 06:41:16.176 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.176 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.176
2025-07-02 06:41:16.176 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.176 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.176 alo = 12, ahi = 1101
2025-07-02 06:41:16.176 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.176 blo = 12, bhi = 1101
2025-07-02 06:41:16.176
2025-07-02 06:41:16.177 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.177 g = []
2025-07-02 06:41:16.177 if alo < ahi:
2025-07-02 06:41:16.177 if blo < bhi:
2025-07-02 06:41:16.177 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.177 else:
2025-07-02 06:41:16.177 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.177 elif blo < bhi:
2025-07-02 06:41:16.177 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.177
2025-07-02 06:41:16.177 > yield from g
2025-07-02 06:41:16.177
2025-07-02 06:41:16.177 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.177 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.177
2025-07-02 06:41:16.177 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.177 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.177 alo = 12, ahi = 1101
2025-07-02 06:41:16.177 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.177 blo = 12, bhi = 1101
2025-07-02 06:41:16.178
2025-07-02 06:41:16.178 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.178 r"""
2025-07-02 06:41:16.178 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.178 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.178 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.178 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.178
2025-07-02 06:41:16.178 Example:
2025-07-02 06:41:16.178
2025-07-02 06:41:16.178 >>> d = Differ()
2025-07-02 06:41:16.178 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.178 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.178 >>> print(''.join(results), end="")
2025-07-02 06:41:16.178 - abcDefghiJkl
2025-07-02 06:41:16.178 + abcdefGhijkl
2025-07-02 06:41:16.178 """
2025-07-02 06:41:16.179
2025-07-02 06:41:16.179 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.179 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.179 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.179 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.179 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.179
2025-07-02 06:41:16.179 # search for the pair that matches best without being identical
2025-07-02 06:41:16.179 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.179 # on junk -- unless we have to)
2025-07-02 06:41:16.179 for j in range(blo, bhi):
2025-07-02 06:41:16.179 bj = b[j]
2025-07-02 06:41:16.179 cruncher.set_seq2(bj)
2025-07-02 06:41:16.179 for i in range(alo, ahi):
2025-07-02 06:41:16.179 ai = a[i]
2025-07-02 06:41:16.179 if ai == bj:
2025-07-02 06:41:16.179 if eqi is None:
2025-07-02 06:41:16.179 eqi, eqj = i, j
2025-07-02 06:41:16.179 continue
2025-07-02 06:41:16.180 cruncher.set_seq1(ai)
2025-07-02 06:41:16.180 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.180 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.180 # compares by a factor of 3.
2025-07-02 06:41:16.180 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.180 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.180 # of the computation is cached by cruncher
2025-07-02 06:41:16.180 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.180 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.180 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.180 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.180 if best_ratio < cutoff:
2025-07-02 06:41:16.180 # no non-identical "pretty close" pair
2025-07-02 06:41:16.180 if eqi is None:
2025-07-02 06:41:16.180 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.180 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.180 return
2025-07-02 06:41:16.180 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.180 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.180 else:
2025-07-02 06:41:16.181 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.181 eqi = None
2025-07-02 06:41:16.181
2025-07-02 06:41:16.181 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.181 # identical
2025-07-02 06:41:16.181
2025-07-02 06:41:16.181 # pump out diffs from before the synch point
2025-07-02 06:41:16.181 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.181
2025-07-02 06:41:16.181 # do intraline marking on the synch pair
2025-07-02 06:41:16.181 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.181 if eqi is None:
2025-07-02 06:41:16.181 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.181 atags = btags = ""
2025-07-02 06:41:16.181 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.181 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.181 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.181 if tag == 'replace':
2025-07-02 06:41:16.181 atags += '^' * la
2025-07-02 06:41:16.181 btags += '^' * lb
2025-07-02 06:41:16.182 elif tag == 'delete':
2025-07-02 06:41:16.182 atags += '-' * la
2025-07-02 06:41:16.182 elif tag == 'insert':
2025-07-02 06:41:16.182 btags += '+' * lb
2025-07-02 06:41:16.182 elif tag == 'equal':
2025-07-02 06:41:16.182 atags += ' ' * la
2025-07-02 06:41:16.182 btags += ' ' * lb
2025-07-02 06:41:16.182 else:
2025-07-02 06:41:16.182 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.182 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.182 else:
2025-07-02 06:41:16.182 # the synch pair is identical
2025-07-02 06:41:16.182 yield ' ' + aelt
2025-07-02 06:41:16.182
2025-07-02 06:41:16.182 # pump out diffs from after the synch point
2025-07-02 06:41:16.182 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.182
2025-07-02 06:41:16.182 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.182 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.182
2025-07-02 06:41:16.182 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.183 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.183 alo = 13, ahi = 1101
2025-07-02 06:41:16.183 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.183 blo = 13, bhi = 1101
2025-07-02 06:41:16.183
2025-07-02 06:41:16.183 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.183 g = []
2025-07-02 06:41:16.183 if alo < ahi:
2025-07-02 06:41:16.183 if blo < bhi:
2025-07-02 06:41:16.183 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.183 else:
2025-07-02 06:41:16.183 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.183 elif blo < bhi:
2025-07-02 06:41:16.183 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.183
2025-07-02 06:41:16.183 > yield from g
2025-07-02 06:41:16.183
2025-07-02 06:41:16.183 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.183 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.183
2025-07-02 06:41:16.184 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.184 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.184 alo = 13, ahi = 1101
2025-07-02 06:41:16.184 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.184 blo = 13, bhi = 1101
2025-07-02 06:41:16.184
2025-07-02 06:41:16.184 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.184 r"""
2025-07-02 06:41:16.184 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.184 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.184 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.184 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.184
2025-07-02 06:41:16.184 Example:
2025-07-02 06:41:16.184
2025-07-02 06:41:16.184 >>> d = Differ()
2025-07-02 06:41:16.184 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.184 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.184 >>> print(''.join(results), end="")
2025-07-02 06:41:16.184 - abcDefghiJkl
2025-07-02 06:41:16.185 + abcdefGhijkl
2025-07-02 06:41:16.185 """
2025-07-02 06:41:16.185
2025-07-02 06:41:16.185 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.185 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.185 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.185 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.185 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.185
2025-07-02 06:41:16.185 # search for the pair that matches best without being identical
2025-07-02 06:41:16.185 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.185 # on junk -- unless we have to)
2025-07-02 06:41:16.185 for j in range(blo, bhi):
2025-07-02 06:41:16.185 bj = b[j]
2025-07-02 06:41:16.185 cruncher.set_seq2(bj)
2025-07-02 06:41:16.185 for i in range(alo, ahi):
2025-07-02 06:41:16.185 ai = a[i]
2025-07-02 06:41:16.185 if ai == bj:
2025-07-02 06:41:16.186 if eqi is None:
2025-07-02 06:41:16.186 eqi, eqj = i, j
2025-07-02 06:41:16.186 continue
2025-07-02 06:41:16.186 cruncher.set_seq1(ai)
2025-07-02 06:41:16.186 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.186 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.186 # compares by a factor of 3.
2025-07-02 06:41:16.186 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.186 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.186 # of the computation is cached by cruncher
2025-07-02 06:41:16.186 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.186 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.186 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.186 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.186 if best_ratio < cutoff:
2025-07-02 06:41:16.186 # no non-identical "pretty close" pair
2025-07-02 06:41:16.186 if eqi is None:
2025-07-02 06:41:16.186 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.186 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.186 return
2025-07-02 06:41:16.186 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.187 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.187 else:
2025-07-02 06:41:16.187 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.187 eqi = None
2025-07-02 06:41:16.187
2025-07-02 06:41:16.187 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.187 # identical
2025-07-02 06:41:16.187
2025-07-02 06:41:16.187 # pump out diffs from before the synch point
2025-07-02 06:41:16.187 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.187
2025-07-02 06:41:16.187 # do intraline marking on the synch pair
2025-07-02 06:41:16.187 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.187 if eqi is None:
2025-07-02 06:41:16.187 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.187 atags = btags = ""
2025-07-02 06:41:16.188 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.188 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.188 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.188 if tag == 'replace':
2025-07-02 06:41:16.188 atags += '^' * la
2025-07-02 06:41:16.188 btags += '^' * lb
2025-07-02 06:41:16.188 elif tag == 'delete':
2025-07-02 06:41:16.188 atags += '-' * la
2025-07-02 06:41:16.188 elif tag == 'insert':
2025-07-02 06:41:16.188 btags += '+' * lb
2025-07-02 06:41:16.188 elif tag == 'equal':
2025-07-02 06:41:16.188 atags += ' ' * la
2025-07-02 06:41:16.188 btags += ' ' * lb
2025-07-02 06:41:16.188 else:
2025-07-02 06:41:16.188 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.188 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.188 else:
2025-07-02 06:41:16.188 # the synch pair is identical
2025-07-02 06:41:16.188 yield ' ' + aelt
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189 # pump out diffs from after the synch point
2025-07-02 06:41:16.189 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.189 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.189 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.189 alo = 14, ahi = 1101
2025-07-02 06:41:16.189 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.189 blo = 14, bhi = 1101
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.189 g = []
2025-07-02 06:41:16.189 if alo < ahi:
2025-07-02 06:41:16.189 if blo < bhi:
2025-07-02 06:41:16.189 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.190 else:
2025-07-02 06:41:16.190 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.190 elif blo < bhi:
2025-07-02 06:41:16.190 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 > yield from g
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.190 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.190 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.190 alo = 14, ahi = 1101
2025-07-02 06:41:16.190 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.190 blo = 14, bhi = 1101
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.190 r"""
2025-07-02 06:41:16.190 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.190 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.191 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.191 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.191
2025-07-02 06:41:16.191 Example:
2025-07-02 06:41:16.191
2025-07-02 06:41:16.191 >>> d = Differ()
2025-07-02 06:41:16.191 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.191 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.191 >>> print(''.join(results), end="")
2025-07-02 06:41:16.191 - abcDefghiJkl
2025-07-02 06:41:16.191 + abcdefGhijkl
2025-07-02 06:41:16.191 """
2025-07-02 06:41:16.191
2025-07-02 06:41:16.191 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.191 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.191 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.191 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.191 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.192
2025-07-02 06:41:16.192 # search for the pair that matches best without being identical
2025-07-02 06:41:16.192 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.192 # on junk -- unless we have to)
2025-07-02 06:41:16.192 for j in range(blo, bhi):
2025-07-02 06:41:16.192 bj = b[j]
2025-07-02 06:41:16.192 cruncher.set_seq2(bj)
2025-07-02 06:41:16.192 for i in range(alo, ahi):
2025-07-02 06:41:16.192 ai = a[i]
2025-07-02 06:41:16.192 if ai == bj:
2025-07-02 06:41:16.192 if eqi is None:
2025-07-02 06:41:16.192 eqi, eqj = i, j
2025-07-02 06:41:16.192 continue
2025-07-02 06:41:16.192 cruncher.set_seq1(ai)
2025-07-02 06:41:16.192 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.192 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.192 # compares by a factor of 3.
2025-07-02 06:41:16.192 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.193 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.193 # of the computation is cached by cruncher
2025-07-02 06:41:16.193 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.193 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.193 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.193 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.193 if best_ratio < cutoff:
2025-07-02 06:41:16.193 # no non-identical "pretty close" pair
2025-07-02 06:41:16.193 if eqi is None:
2025-07-02 06:41:16.193 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.193 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.193 return
2025-07-02 06:41:16.193 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.193 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.193 else:
2025-07-02 06:41:16.193 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.193 eqi = None
2025-07-02 06:41:16.193
2025-07-02 06:41:16.193 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.193 # identical
2025-07-02 06:41:16.194
2025-07-02 06:41:16.194 # pump out diffs from before the synch point
2025-07-02 06:41:16.194 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.194
2025-07-02 06:41:16.194 # do intraline marking on the synch pair
2025-07-02 06:41:16.194 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.194 if eqi is None:
2025-07-02 06:41:16.194 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.194 atags = btags = ""
2025-07-02 06:41:16.194 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.194 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.194 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.194 if tag == 'replace':
2025-07-02 06:41:16.194 atags += '^' * la
2025-07-02 06:41:16.194 btags += '^' * lb
2025-07-02 06:41:16.194 elif tag == 'delete':
2025-07-02 06:41:16.194 atags += '-' * la
2025-07-02 06:41:16.194 elif tag == 'insert':
2025-07-02 06:41:16.194 btags += '+' * lb
2025-07-02 06:41:16.194 elif tag == 'equal':
2025-07-02 06:41:16.195 atags += ' ' * la
2025-07-02 06:41:16.195 btags += ' ' * lb
2025-07-02 06:41:16.195 else:
2025-07-02 06:41:16.195 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.195 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.195 else:
2025-07-02 06:41:16.195 # the synch pair is identical
2025-07-02 06:41:16.195 yield ' ' + aelt
2025-07-02 06:41:16.195
2025-07-02 06:41:16.195 # pump out diffs from after the synch point
2025-07-02 06:41:16.195 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.195
2025-07-02 06:41:16.195 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.195 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.195
2025-07-02 06:41:16.195 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.195 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.195 alo = 15, ahi = 1101
2025-07-02 06:41:16.195 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.195 blo = 15, bhi = 1101
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.196 g = []
2025-07-02 06:41:16.196 if alo < ahi:
2025-07-02 06:41:16.196 if blo < bhi:
2025-07-02 06:41:16.196 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.196 else:
2025-07-02 06:41:16.196 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.196 elif blo < bhi:
2025-07-02 06:41:16.196 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 > yield from g
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.196 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.196 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.197 alo = 15, ahi = 1101
2025-07-02 06:41:16.197 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.197 blo = 15, bhi = 1101
2025-07-02 06:41:16.197
2025-07-02 06:41:16.197 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.197 r"""
2025-07-02 06:41:16.197 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.197 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.197 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.197 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.197
2025-07-02 06:41:16.197 Example:
2025-07-02 06:41:16.197
2025-07-02 06:41:16.197 >>> d = Differ()
2025-07-02 06:41:16.197 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.197 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.197 >>> print(''.join(results), end="")
2025-07-02 06:41:16.197 - abcDefghiJkl
2025-07-02 06:41:16.197 + abcdefGhijkl
2025-07-02 06:41:16.198 """
2025-07-02 06:41:16.198
2025-07-02 06:41:16.198 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.198 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.198 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.198 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.198 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.198
2025-07-02 06:41:16.198 # search for the pair that matches best without being identical
2025-07-02 06:41:16.198 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.198 # on junk -- unless we have to)
2025-07-02 06:41:16.198 for j in range(blo, bhi):
2025-07-02 06:41:16.198 bj = b[j]
2025-07-02 06:41:16.198 cruncher.set_seq2(bj)
2025-07-02 06:41:16.198 for i in range(alo, ahi):
2025-07-02 06:41:16.198 ai = a[i]
2025-07-02 06:41:16.198 if ai == bj:
2025-07-02 06:41:16.198 if eqi is None:
2025-07-02 06:41:16.198 eqi, eqj = i, j
2025-07-02 06:41:16.199 continue
2025-07-02 06:41:16.199 cruncher.set_seq1(ai)
2025-07-02 06:41:16.199 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.199 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.199 # compares by a factor of 3.
2025-07-02 06:41:16.199 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.199 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.199 # of the computation is cached by cruncher
2025-07-02 06:41:16.199 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.199 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.199 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.199 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.199 if best_ratio < cutoff:
2025-07-02 06:41:16.199 # no non-identical "pretty close" pair
2025-07-02 06:41:16.199 if eqi is None:
2025-07-02 06:41:16.199 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.199 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.199 return
2025-07-02 06:41:16.199 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.199 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.200 else:
2025-07-02 06:41:16.200 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.200 eqi = None
2025-07-02 06:41:16.200
2025-07-02 06:41:16.200 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.200 # identical
2025-07-02 06:41:16.200
2025-07-02 06:41:16.200 # pump out diffs from before the synch point
2025-07-02 06:41:16.200 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.200
2025-07-02 06:41:16.200 # do intraline marking on the synch pair
2025-07-02 06:41:16.200 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.200 if eqi is None:
2025-07-02 06:41:16.200 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.200 atags = btags = ""
2025-07-02 06:41:16.200 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.200 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.200 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.200 if tag == 'replace':
2025-07-02 06:41:16.200 atags += '^' * la
2025-07-02 06:41:16.200 btags += '^' * lb
2025-07-02 06:41:16.201 elif tag == 'delete':
2025-07-02 06:41:16.201 atags += '-' * la
2025-07-02 06:41:16.201 elif tag == 'insert':
2025-07-02 06:41:16.201 btags += '+' * lb
2025-07-02 06:41:16.201 elif tag == 'equal':
2025-07-02 06:41:16.201 atags += ' ' * la
2025-07-02 06:41:16.201 btags += ' ' * lb
2025-07-02 06:41:16.201 else:
2025-07-02 06:41:16.201 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.201 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.201 else:
2025-07-02 06:41:16.201 # the synch pair is identical
2025-07-02 06:41:16.201 yield ' ' + aelt
2025-07-02 06:41:16.201
2025-07-02 06:41:16.201 # pump out diffs from after the synch point
2025-07-02 06:41:16.201 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.201
2025-07-02 06:41:16.201 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.201 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.201
2025-07-02 06:41:16.201 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.202 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.202 alo = 16, ahi = 1101
2025-07-02 06:41:16.202 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.202 blo = 16, bhi = 1101
2025-07-02 06:41:16.202
2025-07-02 06:41:16.202 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.202 g = []
2025-07-02 06:41:16.202 if alo < ahi:
2025-07-02 06:41:16.202 if blo < bhi:
2025-07-02 06:41:16.202 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.202 else:
2025-07-02 06:41:16.202 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.202 elif blo < bhi:
2025-07-02 06:41:16.202 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.202
2025-07-02 06:41:16.202 > yield from g
2025-07-02 06:41:16.202
2025-07-02 06:41:16.202 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.202 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.202
2025-07-02 06:41:16.203 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.203 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.203 alo = 16, ahi = 1101
2025-07-02 06:41:16.203 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.203 blo = 16, bhi = 1101
2025-07-02 06:41:16.203
2025-07-02 06:41:16.203 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.203 r"""
2025-07-02 06:41:16.203 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.203 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.203 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.203 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.203
2025-07-02 06:41:16.203 Example:
2025-07-02 06:41:16.203
2025-07-02 06:41:16.203 >>> d = Differ()
2025-07-02 06:41:16.203 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.203 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.203 >>> print(''.join(results), end="")
2025-07-02 06:41:16.203 - abcDefghiJkl
2025-07-02 06:41:16.204 + abcdefGhijkl
2025-07-02 06:41:16.204 """
2025-07-02 06:41:16.204
2025-07-02 06:41:16.204 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.204 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.204 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.204 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.204 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.204
2025-07-02 06:41:16.204 # search for the pair that matches best without being identical
2025-07-02 06:41:16.204 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.204 # on junk -- unless we have to)
2025-07-02 06:41:16.204 for j in range(blo, bhi):
2025-07-02 06:41:16.204 bj = b[j]
2025-07-02 06:41:16.204 cruncher.set_seq2(bj)
2025-07-02 06:41:16.204 for i in range(alo, ahi):
2025-07-02 06:41:16.204 ai = a[i]
2025-07-02 06:41:16.204 if ai == bj:
2025-07-02 06:41:16.204 if eqi is None:
2025-07-02 06:41:16.205 eqi, eqj = i, j
2025-07-02 06:41:16.205 continue
2025-07-02 06:41:16.205 cruncher.set_seq1(ai)
2025-07-02 06:41:16.205 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.205 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.205 # compares by a factor of 3.
2025-07-02 06:41:16.205 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.205 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.205 # of the computation is cached by cruncher
2025-07-02 06:41:16.205 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.205 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.205 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.205 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.205 if best_ratio < cutoff:
2025-07-02 06:41:16.205 # no non-identical "pretty close" pair
2025-07-02 06:41:16.205 if eqi is None:
2025-07-02 06:41:16.205 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.205 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.206 return
2025-07-02 06:41:16.206 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.206 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.206 else:
2025-07-02 06:41:16.206 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.206 eqi = None
2025-07-02 06:41:16.206
2025-07-02 06:41:16.206 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.206 # identical
2025-07-02 06:41:16.206
2025-07-02 06:41:16.206 # pump out diffs from before the synch point
2025-07-02 06:41:16.206 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.206
2025-07-02 06:41:16.206 # do intraline marking on the synch pair
2025-07-02 06:41:16.206 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.206 if eqi is None:
2025-07-02 06:41:16.206 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.206 atags = btags = ""
2025-07-02 06:41:16.206 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.206 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.207 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.207 if tag == 'replace':
2025-07-02 06:41:16.207 atags += '^' * la
2025-07-02 06:41:16.207 btags += '^' * lb
2025-07-02 06:41:16.207 elif tag == 'delete':
2025-07-02 06:41:16.207 atags += '-' * la
2025-07-02 06:41:16.207 elif tag == 'insert':
2025-07-02 06:41:16.207 btags += '+' * lb
2025-07-02 06:41:16.207 elif tag == 'equal':
2025-07-02 06:41:16.207 atags += ' ' * la
2025-07-02 06:41:16.207 btags += ' ' * lb
2025-07-02 06:41:16.207 else:
2025-07-02 06:41:16.207 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.207 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.207 else:
2025-07-02 06:41:16.207 # the synch pair is identical
2025-07-02 06:41:16.207 yield ' ' + aelt
2025-07-02 06:41:16.207
2025-07-02 06:41:16.207 # pump out diffs from after the synch point
2025-07-02 06:41:16.207 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.207
2025-07-02 06:41:16.208 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.208 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.208
2025-07-02 06:41:16.208 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.208 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.208 alo = 17, ahi = 1101
2025-07-02 06:41:16.208 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.208 blo = 17, bhi = 1101
2025-07-02 06:41:16.208
2025-07-02 06:41:16.208 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.208 g = []
2025-07-02 06:41:16.208 if alo < ahi:
2025-07-02 06:41:16.208 if blo < bhi:
2025-07-02 06:41:16.208 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.208 else:
2025-07-02 06:41:16.208 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.208 elif blo < bhi:
2025-07-02 06:41:16.208 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 > yield from g
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.209 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.209 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.209 alo = 17, ahi = 1101
2025-07-02 06:41:16.209 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.209 blo = 17, bhi = 1101
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.209 r"""
2025-07-02 06:41:16.209 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.209 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.209 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.209 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.209
2025-07-02 06:41:16.210 Example:
2025-07-02 06:41:16.210
2025-07-02 06:41:16.210 >>> d = Differ()
2025-07-02 06:41:16.210 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.210 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.210 >>> print(''.join(results), end="")
2025-07-02 06:41:16.210 - abcDefghiJkl
2025-07-02 06:41:16.210 + abcdefGhijkl
2025-07-02 06:41:16.210 """
2025-07-02 06:41:16.210
2025-07-02 06:41:16.210 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.210 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.210 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.210 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.210 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.210
2025-07-02 06:41:16.210 # search for the pair that matches best without being identical
2025-07-02 06:41:16.210 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.210 # on junk -- unless we have to)
2025-07-02 06:41:16.211 for j in range(blo, bhi):
2025-07-02 06:41:16.211 bj = b[j]
2025-07-02 06:41:16.211 cruncher.set_seq2(bj)
2025-07-02 06:41:16.211 for i in range(alo, ahi):
2025-07-02 06:41:16.211 ai = a[i]
2025-07-02 06:41:16.211 if ai == bj:
2025-07-02 06:41:16.211 if eqi is None:
2025-07-02 06:41:16.211 eqi, eqj = i, j
2025-07-02 06:41:16.211 continue
2025-07-02 06:41:16.211 cruncher.set_seq1(ai)
2025-07-02 06:41:16.211 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.211 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.211 # compares by a factor of 3.
2025-07-02 06:41:16.211 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.211 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.211 # of the computation is cached by cruncher
2025-07-02 06:41:16.211 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.211 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.211 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.211 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.212 if best_ratio < cutoff:
2025-07-02 06:41:16.212 # no non-identical "pretty close" pair
2025-07-02 06:41:16.212 if eqi is None:
2025-07-02 06:41:16.212 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.212 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.212 return
2025-07-02 06:41:16.212 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.212 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.212 else:
2025-07-02 06:41:16.212 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.212 eqi = None
2025-07-02 06:41:16.212
2025-07-02 06:41:16.212 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.212 # identical
2025-07-02 06:41:16.212
2025-07-02 06:41:16.212 # pump out diffs from before the synch point
2025-07-02 06:41:16.212 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.212
2025-07-02 06:41:16.212 # do intraline marking on the synch pair
2025-07-02 06:41:16.212 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.213 if eqi is None:
2025-07-02 06:41:16.213 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.213 atags = btags = ""
2025-07-02 06:41:16.213 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.213 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.213 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.213 if tag == 'replace':
2025-07-02 06:41:16.213 atags += '^' * la
2025-07-02 06:41:16.213 btags += '^' * lb
2025-07-02 06:41:16.213 elif tag == 'delete':
2025-07-02 06:41:16.213 atags += '-' * la
2025-07-02 06:41:16.213 elif tag == 'insert':
2025-07-02 06:41:16.213 btags += '+' * lb
2025-07-02 06:41:16.213 elif tag == 'equal':
2025-07-02 06:41:16.213 atags += ' ' * la
2025-07-02 06:41:16.213 btags += ' ' * lb
2025-07-02 06:41:16.213 else:
2025-07-02 06:41:16.213 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.213 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.214 else:
2025-07-02 06:41:16.214 # the synch pair is identical
2025-07-02 06:41:16.214 yield ' ' + aelt
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214 # pump out diffs from after the synch point
2025-07-02 06:41:16.214 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.214 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.214 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.214 alo = 18, ahi = 1101
2025-07-02 06:41:16.214 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.214 blo = 18, bhi = 1101
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.214 g = []
2025-07-02 06:41:16.215 if alo < ahi:
2025-07-02 06:41:16.215 if blo < bhi:
2025-07-02 06:41:16.215 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.215 else:
2025-07-02 06:41:16.215 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.215 elif blo < bhi:
2025-07-02 06:41:16.215 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 > yield from g
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.215 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.215 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.215 alo = 18, ahi = 1101
2025-07-02 06:41:16.215 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.215 blo = 18, bhi = 1101
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.216 r"""
2025-07-02 06:41:16.216 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.216 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.216 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.216 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.216
2025-07-02 06:41:16.216 Example:
2025-07-02 06:41:16.216
2025-07-02 06:41:16.216 >>> d = Differ()
2025-07-02 06:41:16.216 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.216 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.216 >>> print(''.join(results), end="")
2025-07-02 06:41:16.216 - abcDefghiJkl
2025-07-02 06:41:16.216 + abcdefGhijkl
2025-07-02 06:41:16.216 """
2025-07-02 06:41:16.216
2025-07-02 06:41:16.216 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.216 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.217 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.217 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.217 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.217
2025-07-02 06:41:16.217 # search for the pair that matches best without being identical
2025-07-02 06:41:16.217 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.217 # on junk -- unless we have to)
2025-07-02 06:41:16.217 for j in range(blo, bhi):
2025-07-02 06:41:16.217 bj = b[j]
2025-07-02 06:41:16.217 cruncher.set_seq2(bj)
2025-07-02 06:41:16.217 for i in range(alo, ahi):
2025-07-02 06:41:16.217 ai = a[i]
2025-07-02 06:41:16.217 if ai == bj:
2025-07-02 06:41:16.217 if eqi is None:
2025-07-02 06:41:16.217 eqi, eqj = i, j
2025-07-02 06:41:16.217 continue
2025-07-02 06:41:16.217 cruncher.set_seq1(ai)
2025-07-02 06:41:16.217 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.217 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.217 # compares by a factor of 3.
2025-07-02 06:41:16.217 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.218 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.218 # of the computation is cached by cruncher
2025-07-02 06:41:16.218 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.218 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.218 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.218 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.218 if best_ratio < cutoff:
2025-07-02 06:41:16.218 # no non-identical "pretty close" pair
2025-07-02 06:41:16.218 if eqi is None:
2025-07-02 06:41:16.218 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.218 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.218 return
2025-07-02 06:41:16.218 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.218 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.218 else:
2025-07-02 06:41:16.218 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.218 eqi = None
2025-07-02 06:41:16.218
2025-07-02 06:41:16.218 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.218 # identical
2025-07-02 06:41:16.219
2025-07-02 06:41:16.219 # pump out diffs from before the synch point
2025-07-02 06:41:16.219 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.219
2025-07-02 06:41:16.219 # do intraline marking on the synch pair
2025-07-02 06:41:16.219 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.219 if eqi is None:
2025-07-02 06:41:16.219 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.219 atags = btags = ""
2025-07-02 06:41:16.219 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.219 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.219 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.219 if tag == 'replace':
2025-07-02 06:41:16.219 atags += '^' * la
2025-07-02 06:41:16.219 btags += '^' * lb
2025-07-02 06:41:16.219 elif tag == 'delete':
2025-07-02 06:41:16.219 atags += '-' * la
2025-07-02 06:41:16.219 elif tag == 'insert':
2025-07-02 06:41:16.219 btags += '+' * lb
2025-07-02 06:41:16.219 elif tag == 'equal':
2025-07-02 06:41:16.219 atags += ' ' * la
2025-07-02 06:41:16.220 btags += ' ' * lb
2025-07-02 06:41:16.220 else:
2025-07-02 06:41:16.220 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.220 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.220 else:
2025-07-02 06:41:16.220 # the synch pair is identical
2025-07-02 06:41:16.220 yield ' ' + aelt
2025-07-02 06:41:16.220
2025-07-02 06:41:16.220 # pump out diffs from after the synch point
2025-07-02 06:41:16.220 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.220
2025-07-02 06:41:16.220 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.220 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.220
2025-07-02 06:41:16.220 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.220 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.220 alo = 19, ahi = 1101
2025-07-02 06:41:16.220 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.220 blo = 19, bhi = 1101
2025-07-02 06:41:16.220
2025-07-02 06:41:16.221 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.221 g = []
2025-07-02 06:41:16.221 if alo < ahi:
2025-07-02 06:41:16.221 if blo < bhi:
2025-07-02 06:41:16.221 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.221 else:
2025-07-02 06:41:16.221 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.221 elif blo < bhi:
2025-07-02 06:41:16.221 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.221
2025-07-02 06:41:16.221 > yield from g
2025-07-02 06:41:16.221
2025-07-02 06:41:16.221 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.221 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.221
2025-07-02 06:41:16.221 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.221 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.221 alo = 19, ahi = 1101
2025-07-02 06:41:16.221 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.221 blo = 19, bhi = 1101
2025-07-02 06:41:16.222
2025-07-02 06:41:16.222 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.222 r"""
2025-07-02 06:41:16.222 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.222 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.222 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.222 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.222
2025-07-02 06:41:16.222 Example:
2025-07-02 06:41:16.222
2025-07-02 06:41:16.222 >>> d = Differ()
2025-07-02 06:41:16.222 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.222 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.222 >>> print(''.join(results), end="")
2025-07-02 06:41:16.222 - abcDefghiJkl
2025-07-02 06:41:16.222 + abcdefGhijkl
2025-07-02 06:41:16.222 """
2025-07-02 06:41:16.223
2025-07-02 06:41:16.223 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.223 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.223 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.223 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.223 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.223
2025-07-02 06:41:16.223 # search for the pair that matches best without being identical
2025-07-02 06:41:16.223 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.223 # on junk -- unless we have to)
2025-07-02 06:41:16.223 for j in range(blo, bhi):
2025-07-02 06:41:16.223 bj = b[j]
2025-07-02 06:41:16.223 cruncher.set_seq2(bj)
2025-07-02 06:41:16.223 for i in range(alo, ahi):
2025-07-02 06:41:16.223 ai = a[i]
2025-07-02 06:41:16.223 if ai == bj:
2025-07-02 06:41:16.223 if eqi is None:
2025-07-02 06:41:16.223 eqi, eqj = i, j
2025-07-02 06:41:16.223 continue
2025-07-02 06:41:16.224 cruncher.set_seq1(ai)
2025-07-02 06:41:16.224 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.224 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.224 # compares by a factor of 3.
2025-07-02 06:41:16.224 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.224 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.224 # of the computation is cached by cruncher
2025-07-02 06:41:16.224 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.224 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.224 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.224 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.224 if best_ratio < cutoff:
2025-07-02 06:41:16.224 # no non-identical "pretty close" pair
2025-07-02 06:41:16.224 if eqi is None:
2025-07-02 06:41:16.224 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.224 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.224 return
2025-07-02 06:41:16.224 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.225 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.225 else:
2025-07-02 06:41:16.225 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.225 eqi = None
2025-07-02 06:41:16.225
2025-07-02 06:41:16.225 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.225 # identical
2025-07-02 06:41:16.225
2025-07-02 06:41:16.225 # pump out diffs from before the synch point
2025-07-02 06:41:16.225 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.225
2025-07-02 06:41:16.225 # do intraline marking on the synch pair
2025-07-02 06:41:16.225 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.225 if eqi is None:
2025-07-02 06:41:16.225 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.225 atags = btags = ""
2025-07-02 06:41:16.225 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.225 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.225 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.225 if tag == 'replace':
2025-07-02 06:41:16.226 atags += '^' * la
2025-07-02 06:41:16.226 btags += '^' * lb
2025-07-02 06:41:16.226 elif tag == 'delete':
2025-07-02 06:41:16.226 atags += '-' * la
2025-07-02 06:41:16.226 elif tag == 'insert':
2025-07-02 06:41:16.226 btags += '+' * lb
2025-07-02 06:41:16.226 elif tag == 'equal':
2025-07-02 06:41:16.226 atags += ' ' * la
2025-07-02 06:41:16.226 btags += ' ' * lb
2025-07-02 06:41:16.226 else:
2025-07-02 06:41:16.226 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.226 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.226 else:
2025-07-02 06:41:16.226 # the synch pair is identical
2025-07-02 06:41:16.226 yield ' ' + aelt
2025-07-02 06:41:16.226
2025-07-02 06:41:16.226 # pump out diffs from after the synch point
2025-07-02 06:41:16.226 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.226
2025-07-02 06:41:16.226 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.227 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.227
2025-07-02 06:41:16.227 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.227 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.227 alo = 20, ahi = 1101
2025-07-02 06:41:16.227 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.227 blo = 20, bhi = 1101
2025-07-02 06:41:16.227
2025-07-02 06:41:16.227 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.227 g = []
2025-07-02 06:41:16.227 if alo < ahi:
2025-07-02 06:41:16.227 if blo < bhi:
2025-07-02 06:41:16.227 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.227 else:
2025-07-02 06:41:16.227 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.227 elif blo < bhi:
2025-07-02 06:41:16.227 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.227
2025-07-02 06:41:16.227 > yield from g
2025-07-02 06:41:16.227
2025-07-02 06:41:16.228 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.228 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.228 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.228 alo = 20, ahi = 1101
2025-07-02 06:41:16.228 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.228 blo = 20, bhi = 1101
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.228 r"""
2025-07-02 06:41:16.228 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.228 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.228 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.228 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228 Example:
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228 >>> d = Differ()
2025-07-02 06:41:16.228 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.229 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.229 >>> print(''.join(results), end="")
2025-07-02 06:41:16.229 - abcDefghiJkl
2025-07-02 06:41:16.229 + abcdefGhijkl
2025-07-02 06:41:16.229 """
2025-07-02 06:41:16.229
2025-07-02 06:41:16.229 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.229 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.229 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.229 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.229 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.229
2025-07-02 06:41:16.229 # search for the pair that matches best without being identical
2025-07-02 06:41:16.229 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.229 # on junk -- unless we have to)
2025-07-02 06:41:16.229 for j in range(blo, bhi):
2025-07-02 06:41:16.229 bj = b[j]
2025-07-02 06:41:16.229 cruncher.set_seq2(bj)
2025-07-02 06:41:16.230 for i in range(alo, ahi):
2025-07-02 06:41:16.230 ai = a[i]
2025-07-02 06:41:16.230 if ai == bj:
2025-07-02 06:41:16.230 if eqi is None:
2025-07-02 06:41:16.230 eqi, eqj = i, j
2025-07-02 06:41:16.230 continue
2025-07-02 06:41:16.230 cruncher.set_seq1(ai)
2025-07-02 06:41:16.230 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.230 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.230 # compares by a factor of 3.
2025-07-02 06:41:16.230 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.230 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.230 # of the computation is cached by cruncher
2025-07-02 06:41:16.230 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.230 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.230 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.230 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.230 if best_ratio < cutoff:
2025-07-02 06:41:16.230 # no non-identical "pretty close" pair
2025-07-02 06:41:16.230 if eqi is None:
2025-07-02 06:41:16.231 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.231 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.231 return
2025-07-02 06:41:16.231 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.231 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.231 else:
2025-07-02 06:41:16.231 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.231 eqi = None
2025-07-02 06:41:16.231
2025-07-02 06:41:16.231 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.231 # identical
2025-07-02 06:41:16.231
2025-07-02 06:41:16.231 # pump out diffs from before the synch point
2025-07-02 06:41:16.231 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.231
2025-07-02 06:41:16.231 # do intraline marking on the synch pair
2025-07-02 06:41:16.231 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.231 if eqi is None:
2025-07-02 06:41:16.232 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.232 atags = btags = ""
2025-07-02 06:41:16.232 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.232 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.232 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.232 if tag == 'replace':
2025-07-02 06:41:16.232 atags += '^' * la
2025-07-02 06:41:16.232 btags += '^' * lb
2025-07-02 06:41:16.232 elif tag == 'delete':
2025-07-02 06:41:16.232 atags += '-' * la
2025-07-02 06:41:16.232 elif tag == 'insert':
2025-07-02 06:41:16.232 btags += '+' * lb
2025-07-02 06:41:16.232 elif tag == 'equal':
2025-07-02 06:41:16.232 atags += ' ' * la
2025-07-02 06:41:16.232 btags += ' ' * lb
2025-07-02 06:41:16.232 else:
2025-07-02 06:41:16.232 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.232 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.232 else:
2025-07-02 06:41:16.233 # the synch pair is identical
2025-07-02 06:41:16.233 yield ' ' + aelt
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233 # pump out diffs from after the synch point
2025-07-02 06:41:16.233 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.233 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.233 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.233 alo = 21, ahi = 1101
2025-07-02 06:41:16.233 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.233 blo = 21, bhi = 1101
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.233 g = []
2025-07-02 06:41:16.233 if alo < ahi:
2025-07-02 06:41:16.233 if blo < bhi:
2025-07-02 06:41:16.233 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.234 else:
2025-07-02 06:41:16.234 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.234 elif blo < bhi:
2025-07-02 06:41:16.234 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 > yield from g
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.234 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.234 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.234 alo = 21, ahi = 1101
2025-07-02 06:41:16.234 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.234 blo = 21, bhi = 1101
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.234 r"""
2025-07-02 06:41:16.234 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.235 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.235 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.235 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.235
2025-07-02 06:41:16.235 Example:
2025-07-02 06:41:16.235
2025-07-02 06:41:16.235 >>> d = Differ()
2025-07-02 06:41:16.235 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.235 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.235 >>> print(''.join(results), end="")
2025-07-02 06:41:16.235 - abcDefghiJkl
2025-07-02 06:41:16.235 + abcdefGhijkl
2025-07-02 06:41:16.235 """
2025-07-02 06:41:16.235
2025-07-02 06:41:16.235 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.235 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.235 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.235 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.236 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.236
2025-07-02 06:41:16.236 # search for the pair that matches best without being identical
2025-07-02 06:41:16.236 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.236 # on junk -- unless we have to)
2025-07-02 06:41:16.236 for j in range(blo, bhi):
2025-07-02 06:41:16.236 bj = b[j]
2025-07-02 06:41:16.236 cruncher.set_seq2(bj)
2025-07-02 06:41:16.236 for i in range(alo, ahi):
2025-07-02 06:41:16.236 ai = a[i]
2025-07-02 06:41:16.236 if ai == bj:
2025-07-02 06:41:16.236 if eqi is None:
2025-07-02 06:41:16.236 eqi, eqj = i, j
2025-07-02 06:41:16.236 continue
2025-07-02 06:41:16.236 cruncher.set_seq1(ai)
2025-07-02 06:41:16.236 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.236 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.237 # compares by a factor of 3.
2025-07-02 06:41:16.237 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.237 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.237 # of the computation is cached by cruncher
2025-07-02 06:41:16.237 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.237 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.237 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.237 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.237 if best_ratio < cutoff:
2025-07-02 06:41:16.237 # no non-identical "pretty close" pair
2025-07-02 06:41:16.237 if eqi is None:
2025-07-02 06:41:16.237 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.237 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.237 return
2025-07-02 06:41:16.237 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.237 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.237 else:
2025-07-02 06:41:16.237 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.237 eqi = None
2025-07-02 06:41:16.238
2025-07-02 06:41:16.238 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.238 # identical
2025-07-02 06:41:16.238
2025-07-02 06:41:16.238 # pump out diffs from before the synch point
2025-07-02 06:41:16.238 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.238
2025-07-02 06:41:16.238 # do intraline marking on the synch pair
2025-07-02 06:41:16.238 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.238 if eqi is None:
2025-07-02 06:41:16.238 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.238 atags = btags = ""
2025-07-02 06:41:16.238 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.238 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.238 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.238 if tag == 'replace':
2025-07-02 06:41:16.238 atags += '^' * la
2025-07-02 06:41:16.238 btags += '^' * lb
2025-07-02 06:41:16.238 elif tag == 'delete':
2025-07-02 06:41:16.238 atags += '-' * la
2025-07-02 06:41:16.238 elif tag == 'insert':
2025-07-02 06:41:16.239 btags += '+' * lb
2025-07-02 06:41:16.239 elif tag == 'equal':
2025-07-02 06:41:16.239 atags += ' ' * la
2025-07-02 06:41:16.239 btags += ' ' * lb
2025-07-02 06:41:16.239 else:
2025-07-02 06:41:16.239 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.239 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.239 else:
2025-07-02 06:41:16.239 # the synch pair is identical
2025-07-02 06:41:16.239 yield ' ' + aelt
2025-07-02 06:41:16.239
2025-07-02 06:41:16.239 # pump out diffs from after the synch point
2025-07-02 06:41:16.239 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.239
2025-07-02 06:41:16.239 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.239 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.239
2025-07-02 06:41:16.239 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.239 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.239 alo = 22, ahi = 1101
2025-07-02 06:41:16.240 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.240 blo = 22, bhi = 1101
2025-07-02 06:41:16.240
2025-07-02 06:41:16.240 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.240 g = []
2025-07-02 06:41:16.240 if alo < ahi:
2025-07-02 06:41:16.240 if blo < bhi:
2025-07-02 06:41:16.240 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.240 else:
2025-07-02 06:41:16.240 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.240 elif blo < bhi:
2025-07-02 06:41:16.240 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.240
2025-07-02 06:41:16.240 > yield from g
2025-07-02 06:41:16.240
2025-07-02 06:41:16.240 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.240 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.241 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.241 alo = 22, ahi = 1101
2025-07-02 06:41:16.241 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.241 blo = 22, bhi = 1101
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.241 r"""
2025-07-02 06:41:16.241 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.241 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.241 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.241 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241 Example:
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241 >>> d = Differ()
2025-07-02 06:41:16.241 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.241 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.242 >>> print(''.join(results), end="")
2025-07-02 06:41:16.242 - abcDefghiJkl
2025-07-02 06:41:16.242 + abcdefGhijkl
2025-07-02 06:41:16.242 """
2025-07-02 06:41:16.242
2025-07-02 06:41:16.242 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.242 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.242 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.242 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.242 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.242
2025-07-02 06:41:16.242 # search for the pair that matches best without being identical
2025-07-02 06:41:16.242 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.242 # on junk -- unless we have to)
2025-07-02 06:41:16.242 for j in range(blo, bhi):
2025-07-02 06:41:16.242 bj = b[j]
2025-07-02 06:41:16.242 cruncher.set_seq2(bj)
2025-07-02 06:41:16.242 for i in range(alo, ahi):
2025-07-02 06:41:16.243 ai = a[i]
2025-07-02 06:41:16.243 if ai == bj:
2025-07-02 06:41:16.243 if eqi is None:
2025-07-02 06:41:16.243 eqi, eqj = i, j
2025-07-02 06:41:16.243 continue
2025-07-02 06:41:16.243 cruncher.set_seq1(ai)
2025-07-02 06:41:16.243 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.243 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.243 # compares by a factor of 3.
2025-07-02 06:41:16.243 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.243 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.243 # of the computation is cached by cruncher
2025-07-02 06:41:16.243 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.243 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.243 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.243 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.243 if best_ratio < cutoff:
2025-07-02 06:41:16.243 # no non-identical "pretty close" pair
2025-07-02 06:41:16.243 if eqi is None:
2025-07-02 06:41:16.244 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.244 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.244 return
2025-07-02 06:41:16.244 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.244 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.244 else:
2025-07-02 06:41:16.244 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.244 eqi = None
2025-07-02 06:41:16.244
2025-07-02 06:41:16.244 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.244 # identical
2025-07-02 06:41:16.244
2025-07-02 06:41:16.244 # pump out diffs from before the synch point
2025-07-02 06:41:16.244 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.244
2025-07-02 06:41:16.244 # do intraline marking on the synch pair
2025-07-02 06:41:16.244 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.244 if eqi is None:
2025-07-02 06:41:16.244 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.244 atags = btags = ""
2025-07-02 06:41:16.245 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.245 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.245 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.245 if tag == 'replace':
2025-07-02 06:41:16.245 atags += '^' * la
2025-07-02 06:41:16.245 btags += '^' * lb
2025-07-02 06:41:16.245 elif tag == 'delete':
2025-07-02 06:41:16.245 atags += '-' * la
2025-07-02 06:41:16.245 elif tag == 'insert':
2025-07-02 06:41:16.245 btags += '+' * lb
2025-07-02 06:41:16.245 elif tag == 'equal':
2025-07-02 06:41:16.245 atags += ' ' * la
2025-07-02 06:41:16.245 btags += ' ' * lb
2025-07-02 06:41:16.245 else:
2025-07-02 06:41:16.245 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.245 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.245 else:
2025-07-02 06:41:16.245 # the synch pair is identical
2025-07-02 06:41:16.245 yield ' ' + aelt
2025-07-02 06:41:16.245
2025-07-02 06:41:16.246 # pump out diffs from after the synch point
2025-07-02 06:41:16.246 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.246
2025-07-02 06:41:16.246 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.246 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.246
2025-07-02 06:41:16.246 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.246 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.246 alo = 23, ahi = 1101
2025-07-02 06:41:16.246 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.246 blo = 23, bhi = 1101
2025-07-02 06:41:16.246
2025-07-02 06:41:16.246 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.246 g = []
2025-07-02 06:41:16.246 if alo < ahi:
2025-07-02 06:41:16.246 if blo < bhi:
2025-07-02 06:41:16.246 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.246 else:
2025-07-02 06:41:16.246 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.246 elif blo < bhi:
2025-07-02 06:41:16.246 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 > yield from g
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.247 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.247 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.247 alo = 23, ahi = 1101
2025-07-02 06:41:16.247 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.247 blo = 23, bhi = 1101
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.247 r"""
2025-07-02 06:41:16.247 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.247 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.247 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.247 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 Example:
2025-07-02 06:41:16.248
2025-07-02 06:41:16.248 >>> d = Differ()
2025-07-02 06:41:16.248 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.248 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.248 >>> print(''.join(results), end="")
2025-07-02 06:41:16.248 - abcDefghiJkl
2025-07-02 06:41:16.248 + abcdefGhijkl
2025-07-02 06:41:16.248 """
2025-07-02 06:41:16.248
2025-07-02 06:41:16.248 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.248 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.248 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.248 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.248 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.248
2025-07-02 06:41:16.248 # search for the pair that matches best without being identical
2025-07-02 06:41:16.248 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.249 # on junk -- unless we have to)
2025-07-02 06:41:16.249 for j in range(blo, bhi):
2025-07-02 06:41:16.249 bj = b[j]
2025-07-02 06:41:16.249 cruncher.set_seq2(bj)
2025-07-02 06:41:16.249 for i in range(alo, ahi):
2025-07-02 06:41:16.249 ai = a[i]
2025-07-02 06:41:16.249 if ai == bj:
2025-07-02 06:41:16.249 if eqi is None:
2025-07-02 06:41:16.249 eqi, eqj = i, j
2025-07-02 06:41:16.249 continue
2025-07-02 06:41:16.249 cruncher.set_seq1(ai)
2025-07-02 06:41:16.249 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.249 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.249 # compares by a factor of 3.
2025-07-02 06:41:16.249 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.249 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.249 # of the computation is cached by cruncher
2025-07-02 06:41:16.249 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.249 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.249 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.250 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.250 if best_ratio < cutoff:
2025-07-02 06:41:16.250 # no non-identical "pretty close" pair
2025-07-02 06:41:16.250 if eqi is None:
2025-07-02 06:41:16.250 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.250 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.250 return
2025-07-02 06:41:16.250 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.250 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.250 else:
2025-07-02 06:41:16.250 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.250 eqi = None
2025-07-02 06:41:16.250
2025-07-02 06:41:16.250 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.250 # identical
2025-07-02 06:41:16.250
2025-07-02 06:41:16.250 # pump out diffs from before the synch point
2025-07-02 06:41:16.250 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.250
2025-07-02 06:41:16.251 # do intraline marking on the synch pair
2025-07-02 06:41:16.251 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.251 if eqi is None:
2025-07-02 06:41:16.251 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.251 atags = btags = ""
2025-07-02 06:41:16.251 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.251 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.251 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.251 if tag == 'replace':
2025-07-02 06:41:16.251 atags += '^' * la
2025-07-02 06:41:16.251 btags += '^' * lb
2025-07-02 06:41:16.251 elif tag == 'delete':
2025-07-02 06:41:16.251 atags += '-' * la
2025-07-02 06:41:16.251 elif tag == 'insert':
2025-07-02 06:41:16.251 btags += '+' * lb
2025-07-02 06:41:16.251 elif tag == 'equal':
2025-07-02 06:41:16.251 atags += ' ' * la
2025-07-02 06:41:16.251 btags += ' ' * lb
2025-07-02 06:41:16.251 else:
2025-07-02 06:41:16.251 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.252 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.252 else:
2025-07-02 06:41:16.252 # the synch pair is identical
2025-07-02 06:41:16.252 yield ' ' + aelt
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252 # pump out diffs from after the synch point
2025-07-02 06:41:16.252 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.252 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.252 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.252 alo = 26, ahi = 1101
2025-07-02 06:41:16.252 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.252 blo = 26, bhi = 1101
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.252 g = []
2025-07-02 06:41:16.252 if alo < ahi:
2025-07-02 06:41:16.253 if blo < bhi:
2025-07-02 06:41:16.253 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.253 else:
2025-07-02 06:41:16.253 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.253 elif blo < bhi:
2025-07-02 06:41:16.253 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 > yield from g
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.253 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.253 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.253 alo = 26, ahi = 1101
2025-07-02 06:41:16.253 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.253 blo = 26, bhi = 1101
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.253 r"""
2025-07-02 06:41:16.254 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.254 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.254 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.254 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.254
2025-07-02 06:41:16.254 Example:
2025-07-02 06:41:16.254
2025-07-02 06:41:16.254 >>> d = Differ()
2025-07-02 06:41:16.254 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.254 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.254 >>> print(''.join(results), end="")
2025-07-02 06:41:16.254 - abcDefghiJkl
2025-07-02 06:41:16.254 + abcdefGhijkl
2025-07-02 06:41:16.254 """
2025-07-02 06:41:16.254
2025-07-02 06:41:16.254 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.254 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.254 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.255 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.255 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.255
2025-07-02 06:41:16.255 # search for the pair that matches best without being identical
2025-07-02 06:41:16.255 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.255 # on junk -- unless we have to)
2025-07-02 06:41:16.255 for j in range(blo, bhi):
2025-07-02 06:41:16.255 bj = b[j]
2025-07-02 06:41:16.255 cruncher.set_seq2(bj)
2025-07-02 06:41:16.255 for i in range(alo, ahi):
2025-07-02 06:41:16.255 ai = a[i]
2025-07-02 06:41:16.255 if ai == bj:
2025-07-02 06:41:16.255 if eqi is None:
2025-07-02 06:41:16.255 eqi, eqj = i, j
2025-07-02 06:41:16.255 continue
2025-07-02 06:41:16.255 cruncher.set_seq1(ai)
2025-07-02 06:41:16.255 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.255 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.256 # compares by a factor of 3.
2025-07-02 06:41:16.256 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.256 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.256 # of the computation is cached by cruncher
2025-07-02 06:41:16.256 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.256 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.256 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.256 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.256 if best_ratio < cutoff:
2025-07-02 06:41:16.256 # no non-identical "pretty close" pair
2025-07-02 06:41:16.256 if eqi is None:
2025-07-02 06:41:16.256 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.256 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.256 return
2025-07-02 06:41:16.256 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.256 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.256 else:
2025-07-02 06:41:16.256 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.256 eqi = None
2025-07-02 06:41:16.256
2025-07-02 06:41:16.257 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.257 # identical
2025-07-02 06:41:16.257
2025-07-02 06:41:16.257 # pump out diffs from before the synch point
2025-07-02 06:41:16.257 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.257
2025-07-02 06:41:16.257 # do intraline marking on the synch pair
2025-07-02 06:41:16.257 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.257 if eqi is None:
2025-07-02 06:41:16.257 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.257 atags = btags = ""
2025-07-02 06:41:16.257 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.257 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.257 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.257 if tag == 'replace':
2025-07-02 06:41:16.257 atags += '^' * la
2025-07-02 06:41:16.257 btags += '^' * lb
2025-07-02 06:41:16.257 elif tag == 'delete':
2025-07-02 06:41:16.258 atags += '-' * la
2025-07-02 06:41:16.258 elif tag == 'insert':
2025-07-02 06:41:16.258 btags += '+' * lb
2025-07-02 06:41:16.258 elif tag == 'equal':
2025-07-02 06:41:16.258 atags += ' ' * la
2025-07-02 06:41:16.258 btags += ' ' * lb
2025-07-02 06:41:16.258 else:
2025-07-02 06:41:16.258 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.258 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.258 else:
2025-07-02 06:41:16.258 # the synch pair is identical
2025-07-02 06:41:16.258 yield ' ' + aelt
2025-07-02 06:41:16.258
2025-07-02 06:41:16.258 # pump out diffs from after the synch point
2025-07-02 06:41:16.258 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.258
2025-07-02 06:41:16.258 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.258 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.258
2025-07-02 06:41:16.258 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.259 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.259 alo = 27, ahi = 1101
2025-07-02 06:41:16.259 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.259 blo = 27, bhi = 1101
2025-07-02 06:41:16.259
2025-07-02 06:41:16.259 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.259 g = []
2025-07-02 06:41:16.259 if alo < ahi:
2025-07-02 06:41:16.259 if blo < bhi:
2025-07-02 06:41:16.259 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.259 else:
2025-07-02 06:41:16.259 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.259 elif blo < bhi:
2025-07-02 06:41:16.259 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.259
2025-07-02 06:41:16.259 > yield from g
2025-07-02 06:41:16.259
2025-07-02 06:41:16.259 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.259 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.259
2025-07-02 06:41:16.260 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.260 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.260 alo = 27, ahi = 1101
2025-07-02 06:41:16.260 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.260 blo = 27, bhi = 1101
2025-07-02 06:41:16.260
2025-07-02 06:41:16.260 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.260 r"""
2025-07-02 06:41:16.260 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.260 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.260 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.260 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.260
2025-07-02 06:41:16.260 Example:
2025-07-02 06:41:16.260
2025-07-02 06:41:16.260 >>> d = Differ()
2025-07-02 06:41:16.260 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.260 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.260 >>> print(''.join(results), end="")
2025-07-02 06:41:16.261 - abcDefghiJkl
2025-07-02 06:41:16.261 + abcdefGhijkl
2025-07-02 06:41:16.261 """
2025-07-02 06:41:16.261
2025-07-02 06:41:16.261 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.261 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.261 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.261 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.261 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.261
2025-07-02 06:41:16.261 # search for the pair that matches best without being identical
2025-07-02 06:41:16.261 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.261 # on junk -- unless we have to)
2025-07-02 06:41:16.261 for j in range(blo, bhi):
2025-07-02 06:41:16.261 bj = b[j]
2025-07-02 06:41:16.261 cruncher.set_seq2(bj)
2025-07-02 06:41:16.261 for i in range(alo, ahi):
2025-07-02 06:41:16.261 ai = a[i]
2025-07-02 06:41:16.261 if ai == bj:
2025-07-02 06:41:16.262 if eqi is None:
2025-07-02 06:41:16.262 eqi, eqj = i, j
2025-07-02 06:41:16.262 continue
2025-07-02 06:41:16.262 cruncher.set_seq1(ai)
2025-07-02 06:41:16.262 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.262 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.262 # compares by a factor of 3.
2025-07-02 06:41:16.262 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.262 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.262 # of the computation is cached by cruncher
2025-07-02 06:41:16.262 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.262 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.262 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.262 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.262 if best_ratio < cutoff:
2025-07-02 06:41:16.262 # no non-identical "pretty close" pair
2025-07-02 06:41:16.262 if eqi is None:
2025-07-02 06:41:16.262 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.262 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.262 return
2025-07-02 06:41:16.263 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.263 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.263 else:
2025-07-02 06:41:16.263 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.263 eqi = None
2025-07-02 06:41:16.263
2025-07-02 06:41:16.263 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.263 # identical
2025-07-02 06:41:16.263
2025-07-02 06:41:16.263 # pump out diffs from before the synch point
2025-07-02 06:41:16.263 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.263
2025-07-02 06:41:16.263 # do intraline marking on the synch pair
2025-07-02 06:41:16.263 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.263 if eqi is None:
2025-07-02 06:41:16.263 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.263 atags = btags = ""
2025-07-02 06:41:16.263 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.263 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.263 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.263 if tag == 'replace':
2025-07-02 06:41:16.264 atags += '^' * la
2025-07-02 06:41:16.264 btags += '^' * lb
2025-07-02 06:41:16.264 elif tag == 'delete':
2025-07-02 06:41:16.264 atags += '-' * la
2025-07-02 06:41:16.264 elif tag == 'insert':
2025-07-02 06:41:16.264 btags += '+' * lb
2025-07-02 06:41:16.264 elif tag == 'equal':
2025-07-02 06:41:16.264 atags += ' ' * la
2025-07-02 06:41:16.264 btags += ' ' * lb
2025-07-02 06:41:16.264 else:
2025-07-02 06:41:16.264 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.264 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.264 else:
2025-07-02 06:41:16.264 # the synch pair is identical
2025-07-02 06:41:16.264 yield ' ' + aelt
2025-07-02 06:41:16.264
2025-07-02 06:41:16.264 # pump out diffs from after the synch point
2025-07-02 06:41:16.264 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.264
2025-07-02 06:41:16.264 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.264 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.265
2025-07-02 06:41:16.265 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.265 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.265 alo = 28, ahi = 1101
2025-07-02 06:41:16.265 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.265 blo = 28, bhi = 1101
2025-07-02 06:41:16.265
2025-07-02 06:41:16.265 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.265 g = []
2025-07-02 06:41:16.265 if alo < ahi:
2025-07-02 06:41:16.265 if blo < bhi:
2025-07-02 06:41:16.265 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.265 else:
2025-07-02 06:41:16.265 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.265 elif blo < bhi:
2025-07-02 06:41:16.265 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.265
2025-07-02 06:41:16.265 > yield from g
2025-07-02 06:41:16.265
2025-07-02 06:41:16.266 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.266 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.266 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.266 alo = 28, ahi = 1101
2025-07-02 06:41:16.266 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.266 blo = 28, bhi = 1101
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.266 r"""
2025-07-02 06:41:16.266 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.266 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.266 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.266 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266 Example:
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266 >>> d = Differ()
2025-07-02 06:41:16.267 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.267 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.267 >>> print(''.join(results), end="")
2025-07-02 06:41:16.267 - abcDefghiJkl
2025-07-02 06:41:16.267 + abcdefGhijkl
2025-07-02 06:41:16.267 """
2025-07-02 06:41:16.267
2025-07-02 06:41:16.267 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.267 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.267 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.267 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.267 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.267
2025-07-02 06:41:16.267 # search for the pair that matches best without being identical
2025-07-02 06:41:16.267 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.267 # on junk -- unless we have to)
2025-07-02 06:41:16.267 for j in range(blo, bhi):
2025-07-02 06:41:16.267 bj = b[j]
2025-07-02 06:41:16.268 cruncher.set_seq2(bj)
2025-07-02 06:41:16.268 for i in range(alo, ahi):
2025-07-02 06:41:16.268 ai = a[i]
2025-07-02 06:41:16.268 if ai == bj:
2025-07-02 06:41:16.268 if eqi is None:
2025-07-02 06:41:16.268 eqi, eqj = i, j
2025-07-02 06:41:16.268 continue
2025-07-02 06:41:16.268 cruncher.set_seq1(ai)
2025-07-02 06:41:16.268 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.268 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.268 # compares by a factor of 3.
2025-07-02 06:41:16.268 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.268 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.268 # of the computation is cached by cruncher
2025-07-02 06:41:16.268 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.268 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.268 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.268 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.268 if best_ratio < cutoff:
2025-07-02 06:41:16.269 # no non-identical "pretty close" pair
2025-07-02 06:41:16.269 if eqi is None:
2025-07-02 06:41:16.269 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.269 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.269 return
2025-07-02 06:41:16.269 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.269 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.269 else:
2025-07-02 06:41:16.269 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.269 eqi = None
2025-07-02 06:41:16.269
2025-07-02 06:41:16.269 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.269 # identical
2025-07-02 06:41:16.269
2025-07-02 06:41:16.269 # pump out diffs from before the synch point
2025-07-02 06:41:16.269 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.269
2025-07-02 06:41:16.269 # do intraline marking on the synch pair
2025-07-02 06:41:16.269 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.269 if eqi is None:
2025-07-02 06:41:16.269 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.270 atags = btags = ""
2025-07-02 06:41:16.270 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.270 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.270 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.270 if tag == 'replace':
2025-07-02 06:41:16.270 atags += '^' * la
2025-07-02 06:41:16.270 btags += '^' * lb
2025-07-02 06:41:16.270 elif tag == 'delete':
2025-07-02 06:41:16.270 atags += '-' * la
2025-07-02 06:41:16.270 elif tag == 'insert':
2025-07-02 06:41:16.270 btags += '+' * lb
2025-07-02 06:41:16.270 elif tag == 'equal':
2025-07-02 06:41:16.270 atags += ' ' * la
2025-07-02 06:41:16.270 btags += ' ' * lb
2025-07-02 06:41:16.270 else:
2025-07-02 06:41:16.270 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.270 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.270 else:
2025-07-02 06:41:16.271 # the synch pair is identical
2025-07-02 06:41:16.271 yield ' ' + aelt
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271 # pump out diffs from after the synch point
2025-07-02 06:41:16.271 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.271 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.271 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.271 alo = 29, ahi = 1101
2025-07-02 06:41:16.271 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.271 blo = 29, bhi = 1101
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.271 g = []
2025-07-02 06:41:16.271 if alo < ahi:
2025-07-02 06:41:16.271 if blo < bhi:
2025-07-02 06:41:16.272 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.272 else:
2025-07-02 06:41:16.272 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.272 elif blo < bhi:
2025-07-02 06:41:16.272 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 > yield from g
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.272 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.272 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.272 alo = 29, ahi = 1101
2025-07-02 06:41:16.272 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.272 blo = 29, bhi = 1101
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.272 r"""
2025-07-02 06:41:16.272 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.273 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.273 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.273 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.273
2025-07-02 06:41:16.273 Example:
2025-07-02 06:41:16.273
2025-07-02 06:41:16.273 >>> d = Differ()
2025-07-02 06:41:16.273 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.273 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.273 >>> print(''.join(results), end="")
2025-07-02 06:41:16.273 - abcDefghiJkl
2025-07-02 06:41:16.273 + abcdefGhijkl
2025-07-02 06:41:16.273 """
2025-07-02 06:41:16.273
2025-07-02 06:41:16.273 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.273 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.273 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.273 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.274 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.274
2025-07-02 06:41:16.274 # search for the pair that matches best without being identical
2025-07-02 06:41:16.274 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.274 # on junk -- unless we have to)
2025-07-02 06:41:16.274 for j in range(blo, bhi):
2025-07-02 06:41:16.274 bj = b[j]
2025-07-02 06:41:16.274 cruncher.set_seq2(bj)
2025-07-02 06:41:16.274 for i in range(alo, ahi):
2025-07-02 06:41:16.274 ai = a[i]
2025-07-02 06:41:16.274 if ai == bj:
2025-07-02 06:41:16.274 if eqi is None:
2025-07-02 06:41:16.274 eqi, eqj = i, j
2025-07-02 06:41:16.274 continue
2025-07-02 06:41:16.274 cruncher.set_seq1(ai)
2025-07-02 06:41:16.274 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.274 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.274 # compares by a factor of 3.
2025-07-02 06:41:16.274 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.275 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.275 # of the computation is cached by cruncher
2025-07-02 06:41:16.275 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.275 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.275 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.275 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.275 if best_ratio < cutoff:
2025-07-02 06:41:16.275 # no non-identical "pretty close" pair
2025-07-02 06:41:16.275 if eqi is None:
2025-07-02 06:41:16.275 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.275 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.275 return
2025-07-02 06:41:16.275 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.275 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.275 else:
2025-07-02 06:41:16.275 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.275 eqi = None
2025-07-02 06:41:16.275
2025-07-02 06:41:16.275 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.276 # identical
2025-07-02 06:41:16.276
2025-07-02 06:41:16.276 # pump out diffs from before the synch point
2025-07-02 06:41:16.276 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.276
2025-07-02 06:41:16.276 # do intraline marking on the synch pair
2025-07-02 06:41:16.276 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.276 if eqi is None:
2025-07-02 06:41:16.276 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.276 atags = btags = ""
2025-07-02 06:41:16.276 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.276 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.276 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.276 if tag == 'replace':
2025-07-02 06:41:16.276 atags += '^' * la
2025-07-02 06:41:16.276 btags += '^' * lb
2025-07-02 06:41:16.276 elif tag == 'delete':
2025-07-02 06:41:16.276 atags += '-' * la
2025-07-02 06:41:16.276 elif tag == 'insert':
2025-07-02 06:41:16.277 btags += '+' * lb
2025-07-02 06:41:16.277 elif tag == 'equal':
2025-07-02 06:41:16.277 atags += ' ' * la
2025-07-02 06:41:16.277 btags += ' ' * lb
2025-07-02 06:41:16.277 else:
2025-07-02 06:41:16.277 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.277 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.277 else:
2025-07-02 06:41:16.277 # the synch pair is identical
2025-07-02 06:41:16.277 yield ' ' + aelt
2025-07-02 06:41:16.277
2025-07-02 06:41:16.277 # pump out diffs from after the synch point
2025-07-02 06:41:16.277 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.277
2025-07-02 06:41:16.277 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.277 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.277
2025-07-02 06:41:16.277 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.277 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.277 alo = 30, ahi = 1101
2025-07-02 06:41:16.278 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.278 blo = 30, bhi = 1101
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.278 g = []
2025-07-02 06:41:16.278 if alo < ahi:
2025-07-02 06:41:16.278 if blo < bhi:
2025-07-02 06:41:16.278 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.278 else:
2025-07-02 06:41:16.278 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.278 elif blo < bhi:
2025-07-02 06:41:16.278 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 > yield from g
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.278 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.278 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.279 alo = 30, ahi = 1101
2025-07-02 06:41:16.279 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.279 blo = 30, bhi = 1101
2025-07-02 06:41:16.279
2025-07-02 06:41:16.279 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.279 r"""
2025-07-02 06:41:16.279 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.279 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.279 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.279 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.279
2025-07-02 06:41:16.279 Example:
2025-07-02 06:41:16.279
2025-07-02 06:41:16.279 >>> d = Differ()
2025-07-02 06:41:16.279 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.279 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.279 >>> print(''.join(results), end="")
2025-07-02 06:41:16.279 - abcDefghiJkl
2025-07-02 06:41:16.279 + abcdefGhijkl
2025-07-02 06:41:16.280 """
2025-07-02 06:41:16.280
2025-07-02 06:41:16.280 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.280 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.280 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.280 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.280 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.280
2025-07-02 06:41:16.280 # search for the pair that matches best without being identical
2025-07-02 06:41:16.280 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.280 # on junk -- unless we have to)
2025-07-02 06:41:16.280 for j in range(blo, bhi):
2025-07-02 06:41:16.280 bj = b[j]
2025-07-02 06:41:16.280 cruncher.set_seq2(bj)
2025-07-02 06:41:16.280 for i in range(alo, ahi):
2025-07-02 06:41:16.280 ai = a[i]
2025-07-02 06:41:16.280 if ai == bj:
2025-07-02 06:41:16.280 if eqi is None:
2025-07-02 06:41:16.280 eqi, eqj = i, j
2025-07-02 06:41:16.280 continue
2025-07-02 06:41:16.281 cruncher.set_seq1(ai)
2025-07-02 06:41:16.281 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.281 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.281 # compares by a factor of 3.
2025-07-02 06:41:16.281 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.281 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.281 # of the computation is cached by cruncher
2025-07-02 06:41:16.281 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.281 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.281 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.281 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.281 if best_ratio < cutoff:
2025-07-02 06:41:16.281 # no non-identical "pretty close" pair
2025-07-02 06:41:16.281 if eqi is None:
2025-07-02 06:41:16.281 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.281 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.281 return
2025-07-02 06:41:16.281 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.281 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.281 else:
2025-07-02 06:41:16.282 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.282 eqi = None
2025-07-02 06:41:16.282
2025-07-02 06:41:16.282 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.282 # identical
2025-07-02 06:41:16.282
2025-07-02 06:41:16.282 # pump out diffs from before the synch point
2025-07-02 06:41:16.282 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.282
2025-07-02 06:41:16.282 # do intraline marking on the synch pair
2025-07-02 06:41:16.282 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.282 if eqi is None:
2025-07-02 06:41:16.282 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.282 atags = btags = ""
2025-07-02 06:41:16.282 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.282 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.282 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.282 if tag == 'replace':
2025-07-02 06:41:16.282 atags += '^' * la
2025-07-02 06:41:16.282 btags += '^' * lb
2025-07-02 06:41:16.282 elif tag == 'delete':
2025-07-02 06:41:16.283 atags += '-' * la
2025-07-02 06:41:16.283 elif tag == 'insert':
2025-07-02 06:41:16.283 btags += '+' * lb
2025-07-02 06:41:16.283 elif tag == 'equal':
2025-07-02 06:41:16.283 atags += ' ' * la
2025-07-02 06:41:16.283 btags += ' ' * lb
2025-07-02 06:41:16.283 else:
2025-07-02 06:41:16.283 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.283 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.283 else:
2025-07-02 06:41:16.283 # the synch pair is identical
2025-07-02 06:41:16.283 yield ' ' + aelt
2025-07-02 06:41:16.283
2025-07-02 06:41:16.283 # pump out diffs from after the synch point
2025-07-02 06:41:16.283 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.283
2025-07-02 06:41:16.283 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.283 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.284 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.284 alo = 31, ahi = 1101
2025-07-02 06:41:16.284 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.284 blo = 31, bhi = 1101
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.284 g = []
2025-07-02 06:41:16.284 if alo < ahi:
2025-07-02 06:41:16.284 if blo < bhi:
2025-07-02 06:41:16.284 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.284 else:
2025-07-02 06:41:16.284 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.284 elif blo < bhi:
2025-07-02 06:41:16.284 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 > yield from g
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.285 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.285 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.285 alo = 31, ahi = 1101
2025-07-02 06:41:16.285 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.285 blo = 31, bhi = 1101
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.285 r"""
2025-07-02 06:41:16.285 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.285 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.285 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.285 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285 Example:
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285 >>> d = Differ()
2025-07-02 06:41:16.285 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.286 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.286 >>> print(''.join(results), end="")
2025-07-02 06:41:16.286 - abcDefghiJkl
2025-07-02 06:41:16.286 + abcdefGhijkl
2025-07-02 06:41:16.286 """
2025-07-02 06:41:16.286
2025-07-02 06:41:16.286 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.286 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.286 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.286 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.286 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.286
2025-07-02 06:41:16.286 # search for the pair that matches best without being identical
2025-07-02 06:41:16.286 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.286 # on junk -- unless we have to)
2025-07-02 06:41:16.286 for j in range(blo, bhi):
2025-07-02 06:41:16.286 bj = b[j]
2025-07-02 06:41:16.287 cruncher.set_seq2(bj)
2025-07-02 06:41:16.287 for i in range(alo, ahi):
2025-07-02 06:41:16.287 ai = a[i]
2025-07-02 06:41:16.287 if ai == bj:
2025-07-02 06:41:16.287 if eqi is None:
2025-07-02 06:41:16.287 eqi, eqj = i, j
2025-07-02 06:41:16.287 continue
2025-07-02 06:41:16.287 cruncher.set_seq1(ai)
2025-07-02 06:41:16.287 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.287 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.287 # compares by a factor of 3.
2025-07-02 06:41:16.287 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.287 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.287 # of the computation is cached by cruncher
2025-07-02 06:41:16.287 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.287 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.287 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.287 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.287 if best_ratio < cutoff:
2025-07-02 06:41:16.287 # no non-identical "pretty close" pair
2025-07-02 06:41:16.288 if eqi is None:
2025-07-02 06:41:16.288 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.288 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.288 return
2025-07-02 06:41:16.288 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.288 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.288 else:
2025-07-02 06:41:16.288 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.288 eqi = None
2025-07-02 06:41:16.288
2025-07-02 06:41:16.288 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.288 # identical
2025-07-02 06:41:16.288
2025-07-02 06:41:16.288 # pump out diffs from before the synch point
2025-07-02 06:41:16.288 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.288
2025-07-02 06:41:16.288 # do intraline marking on the synch pair
2025-07-02 06:41:16.288 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.288 if eqi is None:
2025-07-02 06:41:16.288 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.289 atags = btags = ""
2025-07-02 06:41:16.289 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.289 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.289 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.289 if tag == 'replace':
2025-07-02 06:41:16.289 atags += '^' * la
2025-07-02 06:41:16.289 btags += '^' * lb
2025-07-02 06:41:16.289 elif tag == 'delete':
2025-07-02 06:41:16.289 atags += '-' * la
2025-07-02 06:41:16.289 elif tag == 'insert':
2025-07-02 06:41:16.289 btags += '+' * lb
2025-07-02 06:41:16.289 elif tag == 'equal':
2025-07-02 06:41:16.289 atags += ' ' * la
2025-07-02 06:41:16.289 btags += ' ' * lb
2025-07-02 06:41:16.289 else:
2025-07-02 06:41:16.289 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.289 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.289 else:
2025-07-02 06:41:16.289 # the synch pair is identical
2025-07-02 06:41:16.289 yield ' ' + aelt
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290 # pump out diffs from after the synch point
2025-07-02 06:41:16.290 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.290 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.290 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.290 alo = 32, ahi = 1101
2025-07-02 06:41:16.290 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.290 blo = 32, bhi = 1101
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.290 g = []
2025-07-02 06:41:16.290 if alo < ahi:
2025-07-02 06:41:16.290 if blo < bhi:
2025-07-02 06:41:16.290 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.290 else:
2025-07-02 06:41:16.291 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.291 elif blo < bhi:
2025-07-02 06:41:16.291 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 > yield from g
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.291 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.291 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.291 alo = 32, ahi = 1101
2025-07-02 06:41:16.291 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.291 blo = 32, bhi = 1101
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.291 r"""
2025-07-02 06:41:16.291 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.292 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.292 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.292 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.292
2025-07-02 06:41:16.292 Example:
2025-07-02 06:41:16.292
2025-07-02 06:41:16.292 >>> d = Differ()
2025-07-02 06:41:16.292 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.292 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.292 >>> print(''.join(results), end="")
2025-07-02 06:41:16.292 - abcDefghiJkl
2025-07-02 06:41:16.292 + abcdefGhijkl
2025-07-02 06:41:16.292 """
2025-07-02 06:41:16.292
2025-07-02 06:41:16.292 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.292 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.292 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.293 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.293 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.293
2025-07-02 06:41:16.293 # search for the pair that matches best without being identical
2025-07-02 06:41:16.293 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.293 # on junk -- unless we have to)
2025-07-02 06:41:16.293 for j in range(blo, bhi):
2025-07-02 06:41:16.293 bj = b[j]
2025-07-02 06:41:16.293 cruncher.set_seq2(bj)
2025-07-02 06:41:16.293 for i in range(alo, ahi):
2025-07-02 06:41:16.293 ai = a[i]
2025-07-02 06:41:16.293 if ai == bj:
2025-07-02 06:41:16.293 if eqi is None:
2025-07-02 06:41:16.293 eqi, eqj = i, j
2025-07-02 06:41:16.293 continue
2025-07-02 06:41:16.293 cruncher.set_seq1(ai)
2025-07-02 06:41:16.293 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.293 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.293 # compares by a factor of 3.
2025-07-02 06:41:16.293 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.294 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.294 # of the computation is cached by cruncher
2025-07-02 06:41:16.294 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.294 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.294 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.294 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.294 if best_ratio < cutoff:
2025-07-02 06:41:16.294 # no non-identical "pretty close" pair
2025-07-02 06:41:16.294 if eqi is None:
2025-07-02 06:41:16.294 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.294 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.294 return
2025-07-02 06:41:16.294 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.294 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.294 else:
2025-07-02 06:41:16.294 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.294 eqi = None
2025-07-02 06:41:16.294
2025-07-02 06:41:16.294 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.295 # identical
2025-07-02 06:41:16.295
2025-07-02 06:41:16.295 # pump out diffs from before the synch point
2025-07-02 06:41:16.295 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.295
2025-07-02 06:41:16.295 # do intraline marking on the synch pair
2025-07-02 06:41:16.295 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.295 if eqi is None:
2025-07-02 06:41:16.295 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.295 atags = btags = ""
2025-07-02 06:41:16.295 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.295 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.295 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.295 if tag == 'replace':
2025-07-02 06:41:16.295 atags += '^' * la
2025-07-02 06:41:16.295 btags += '^' * lb
2025-07-02 06:41:16.295 elif tag == 'delete':
2025-07-02 06:41:16.295 atags += '-' * la
2025-07-02 06:41:16.295 elif tag == 'insert':
2025-07-02 06:41:16.295 btags += '+' * lb
2025-07-02 06:41:16.295 elif tag == 'equal':
2025-07-02 06:41:16.296 atags += ' ' * la
2025-07-02 06:41:16.296 btags += ' ' * lb
2025-07-02 06:41:16.296 else:
2025-07-02 06:41:16.296 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.296 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.296 else:
2025-07-02 06:41:16.296 # the synch pair is identical
2025-07-02 06:41:16.296 yield ' ' + aelt
2025-07-02 06:41:16.296
2025-07-02 06:41:16.296 # pump out diffs from after the synch point
2025-07-02 06:41:16.296 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.296
2025-07-02 06:41:16.296 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.296 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.296
2025-07-02 06:41:16.296 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.296 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.296 alo = 33, ahi = 1101
2025-07-02 06:41:16.296 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.296 blo = 33, bhi = 1101
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.297 g = []
2025-07-02 06:41:16.297 if alo < ahi:
2025-07-02 06:41:16.297 if blo < bhi:
2025-07-02 06:41:16.297 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.297 else:
2025-07-02 06:41:16.297 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.297 elif blo < bhi:
2025-07-02 06:41:16.297 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 > yield from g
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.297 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.297 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.297 alo = 33, ahi = 1101
2025-07-02 06:41:16.297 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.298 blo = 33, bhi = 1101
2025-07-02 06:41:16.298
2025-07-02 06:41:16.298 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.298 r"""
2025-07-02 06:41:16.298 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.298 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.298 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.298 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.298
2025-07-02 06:41:16.298 Example:
2025-07-02 06:41:16.298
2025-07-02 06:41:16.298 >>> d = Differ()
2025-07-02 06:41:16.298 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.298 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.298 >>> print(''.join(results), end="")
2025-07-02 06:41:16.298 - abcDefghiJkl
2025-07-02 06:41:16.298 + abcdefGhijkl
2025-07-02 06:41:16.298 """
2025-07-02 06:41:16.299
2025-07-02 06:41:16.299 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.299 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.299 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.299 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.299 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.299
2025-07-02 06:41:16.299 # search for the pair that matches best without being identical
2025-07-02 06:41:16.299 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.299 # on junk -- unless we have to)
2025-07-02 06:41:16.299 for j in range(blo, bhi):
2025-07-02 06:41:16.299 bj = b[j]
2025-07-02 06:41:16.299 cruncher.set_seq2(bj)
2025-07-02 06:41:16.299 for i in range(alo, ahi):
2025-07-02 06:41:16.299 ai = a[i]
2025-07-02 06:41:16.299 if ai == bj:
2025-07-02 06:41:16.299 if eqi is None:
2025-07-02 06:41:16.299 eqi, eqj = i, j
2025-07-02 06:41:16.299 continue
2025-07-02 06:41:16.299 cruncher.set_seq1(ai)
2025-07-02 06:41:16.299 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.300 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.300 # compares by a factor of 3.
2025-07-02 06:41:16.300 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.300 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.300 # of the computation is cached by cruncher
2025-07-02 06:41:16.300 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.300 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.300 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.300 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.300 if best_ratio < cutoff:
2025-07-02 06:41:16.300 # no non-identical "pretty close" pair
2025-07-02 06:41:16.300 if eqi is None:
2025-07-02 06:41:16.300 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.300 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.300 return
2025-07-02 06:41:16.300 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.300 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.300 else:
2025-07-02 06:41:16.300 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.301 eqi = None
2025-07-02 06:41:16.301
2025-07-02 06:41:16.301 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.301 # identical
2025-07-02 06:41:16.301
2025-07-02 06:41:16.301 # pump out diffs from before the synch point
2025-07-02 06:41:16.301 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.301
2025-07-02 06:41:16.301 # do intraline marking on the synch pair
2025-07-02 06:41:16.301 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.301 if eqi is None:
2025-07-02 06:41:16.301 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.301 atags = btags = ""
2025-07-02 06:41:16.301 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.301 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.301 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.301 if tag == 'replace':
2025-07-02 06:41:16.301 atags += '^' * la
2025-07-02 06:41:16.301 btags += '^' * lb
2025-07-02 06:41:16.302 elif tag == 'delete':
2025-07-02 06:41:16.302 atags += '-' * la
2025-07-02 06:41:16.302 elif tag == 'insert':
2025-07-02 06:41:16.302 btags += '+' * lb
2025-07-02 06:41:16.302 elif tag == 'equal':
2025-07-02 06:41:16.302 atags += ' ' * la
2025-07-02 06:41:16.302 btags += ' ' * lb
2025-07-02 06:41:16.302 else:
2025-07-02 06:41:16.302 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.302 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.302 else:
2025-07-02 06:41:16.302 # the synch pair is identical
2025-07-02 06:41:16.302 yield ' ' + aelt
2025-07-02 06:41:16.302
2025-07-02 06:41:16.302 # pump out diffs from after the synch point
2025-07-02 06:41:16.302 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.302
2025-07-02 06:41:16.302 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.302 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.303 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.303 alo = 34, ahi = 1101
2025-07-02 06:41:16.303 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.303 blo = 34, bhi = 1101
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.303 g = []
2025-07-02 06:41:16.303 if alo < ahi:
2025-07-02 06:41:16.303 if blo < bhi:
2025-07-02 06:41:16.303 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.303 else:
2025-07-02 06:41:16.303 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.303 elif blo < bhi:
2025-07-02 06:41:16.303 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 > yield from g
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.304 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.304 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.304 alo = 34, ahi = 1101
2025-07-02 06:41:16.304 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.304 blo = 34, bhi = 1101
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.304 r"""
2025-07-02 06:41:16.304 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.304 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.304 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.304 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304 Example:
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304 >>> d = Differ()
2025-07-02 06:41:16.304 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.304 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.305 >>> print(''.join(results), end="")
2025-07-02 06:41:16.305 - abcDefghiJkl
2025-07-02 06:41:16.305 + abcdefGhijkl
2025-07-02 06:41:16.305 """
2025-07-02 06:41:16.305
2025-07-02 06:41:16.305 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.305 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.305 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.305 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.305 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.305
2025-07-02 06:41:16.305 # search for the pair that matches best without being identical
2025-07-02 06:41:16.305 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.305 # on junk -- unless we have to)
2025-07-02 06:41:16.305 for j in range(blo, bhi):
2025-07-02 06:41:16.305 bj = b[j]
2025-07-02 06:41:16.305 cruncher.set_seq2(bj)
2025-07-02 06:41:16.305 for i in range(alo, ahi):
2025-07-02 06:41:16.306 ai = a[i]
2025-07-02 06:41:16.306 if ai == bj:
2025-07-02 06:41:16.306 if eqi is None:
2025-07-02 06:41:16.306 eqi, eqj = i, j
2025-07-02 06:41:16.306 continue
2025-07-02 06:41:16.306 cruncher.set_seq1(ai)
2025-07-02 06:41:16.306 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.306 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.306 # compares by a factor of 3.
2025-07-02 06:41:16.306 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.306 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.306 # of the computation is cached by cruncher
2025-07-02 06:41:16.306 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.306 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.306 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.306 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.306 if best_ratio < cutoff:
2025-07-02 06:41:16.306 # no non-identical "pretty close" pair
2025-07-02 06:41:16.306 if eqi is None:
2025-07-02 06:41:16.306 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.307 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.307 return
2025-07-02 06:41:16.307 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.307 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.307 else:
2025-07-02 06:41:16.307 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.307 eqi = None
2025-07-02 06:41:16.307
2025-07-02 06:41:16.307 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.307 # identical
2025-07-02 06:41:16.307
2025-07-02 06:41:16.307 # pump out diffs from before the synch point
2025-07-02 06:41:16.307 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.307
2025-07-02 06:41:16.307 # do intraline marking on the synch pair
2025-07-02 06:41:16.307 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.307 if eqi is None:
2025-07-02 06:41:16.307 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.307 atags = btags = ""
2025-07-02 06:41:16.307 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.307 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.308 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.308 if tag == 'replace':
2025-07-02 06:41:16.308 atags += '^' * la
2025-07-02 06:41:16.308 btags += '^' * lb
2025-07-02 06:41:16.308 elif tag == 'delete':
2025-07-02 06:41:16.308 atags += '-' * la
2025-07-02 06:41:16.308 elif tag == 'insert':
2025-07-02 06:41:16.308 btags += '+' * lb
2025-07-02 06:41:16.308 elif tag == 'equal':
2025-07-02 06:41:16.308 atags += ' ' * la
2025-07-02 06:41:16.308 btags += ' ' * lb
2025-07-02 06:41:16.308 else:
2025-07-02 06:41:16.308 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.308 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.308 else:
2025-07-02 06:41:16.308 # the synch pair is identical
2025-07-02 06:41:16.308 yield ' ' + aelt
2025-07-02 06:41:16.308
2025-07-02 06:41:16.308 # pump out diffs from after the synch point
2025-07-02 06:41:16.308 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.309
2025-07-02 06:41:16.309 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.309 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.309
2025-07-02 06:41:16.309 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.309 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.309 alo = 35, ahi = 1101
2025-07-02 06:41:16.309 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.309 blo = 35, bhi = 1101
2025-07-02 06:41:16.309
2025-07-02 06:41:16.309 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.309 g = []
2025-07-02 06:41:16.309 if alo < ahi:
2025-07-02 06:41:16.309 if blo < bhi:
2025-07-02 06:41:16.309 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.309 else:
2025-07-02 06:41:16.309 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.309 elif blo < bhi:
2025-07-02 06:41:16.310 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 > yield from g
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.310 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.310 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.310 alo = 35, ahi = 1101
2025-07-02 06:41:16.310 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.310 blo = 35, bhi = 1101
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.310 r"""
2025-07-02 06:41:16.310 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.310 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.310 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.310 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311 Example:
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311 >>> d = Differ()
2025-07-02 06:41:16.311 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.311 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.311 >>> print(''.join(results), end="")
2025-07-02 06:41:16.311 - abcDefghiJkl
2025-07-02 06:41:16.311 + abcdefGhijkl
2025-07-02 06:41:16.311 """
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.311 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.311 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.311 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.311 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311 # search for the pair that matches best without being identical
2025-07-02 06:41:16.312 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.312 # on junk -- unless we have to)
2025-07-02 06:41:16.312 for j in range(blo, bhi):
2025-07-02 06:41:16.312 bj = b[j]
2025-07-02 06:41:16.312 cruncher.set_seq2(bj)
2025-07-02 06:41:16.312 for i in range(alo, ahi):
2025-07-02 06:41:16.312 ai = a[i]
2025-07-02 06:41:16.312 if ai == bj:
2025-07-02 06:41:16.312 if eqi is None:
2025-07-02 06:41:16.312 eqi, eqj = i, j
2025-07-02 06:41:16.312 continue
2025-07-02 06:41:16.312 cruncher.set_seq1(ai)
2025-07-02 06:41:16.312 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.312 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.312 # compares by a factor of 3.
2025-07-02 06:41:16.312 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.312 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.312 # of the computation is cached by cruncher
2025-07-02 06:41:16.312 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.312 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.313 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.313 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.313 if best_ratio < cutoff:
2025-07-02 06:41:16.313 # no non-identical "pretty close" pair
2025-07-02 06:41:16.313 if eqi is None:
2025-07-02 06:41:16.313 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.313 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.313 return
2025-07-02 06:41:16.313 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.313 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.313 else:
2025-07-02 06:41:16.313 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.313 eqi = None
2025-07-02 06:41:16.313
2025-07-02 06:41:16.313 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.313 # identical
2025-07-02 06:41:16.313
2025-07-02 06:41:16.313 # pump out diffs from before the synch point
2025-07-02 06:41:16.313 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.313
2025-07-02 06:41:16.313 # do intraline marking on the synch pair
2025-07-02 06:41:16.314 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.314 if eqi is None:
2025-07-02 06:41:16.314 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.314 atags = btags = ""
2025-07-02 06:41:16.314 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.314 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.314 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.314 if tag == 'replace':
2025-07-02 06:41:16.314 atags += '^' * la
2025-07-02 06:41:16.314 btags += '^' * lb
2025-07-02 06:41:16.314 elif tag == 'delete':
2025-07-02 06:41:16.314 atags += '-' * la
2025-07-02 06:41:16.314 elif tag == 'insert':
2025-07-02 06:41:16.314 btags += '+' * lb
2025-07-02 06:41:16.314 elif tag == 'equal':
2025-07-02 06:41:16.314 atags += ' ' * la
2025-07-02 06:41:16.314 btags += ' ' * lb
2025-07-02 06:41:16.314 else:
2025-07-02 06:41:16.314 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.314 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.315 else:
2025-07-02 06:41:16.315 # the synch pair is identical
2025-07-02 06:41:16.315 yield ' ' + aelt
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315 # pump out diffs from after the synch point
2025-07-02 06:41:16.315 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.315 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.315 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.315 alo = 36, ahi = 1101
2025-07-02 06:41:16.315 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.315 blo = 36, bhi = 1101
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.315 g = []
2025-07-02 06:41:16.315 if alo < ahi:
2025-07-02 06:41:16.315 if blo < bhi:
2025-07-02 06:41:16.315 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.316 else:
2025-07-02 06:41:16.316 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.316 elif blo < bhi:
2025-07-02 06:41:16.316 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 > yield from g
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.316 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.316 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.316 alo = 36, ahi = 1101
2025-07-02 06:41:16.316 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.316 blo = 36, bhi = 1101
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.316 r"""
2025-07-02 06:41:16.316 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.316 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.317 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.317 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.317
2025-07-02 06:41:16.317 Example:
2025-07-02 06:41:16.317
2025-07-02 06:41:16.317 >>> d = Differ()
2025-07-02 06:41:16.317 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.317 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.317 >>> print(''.join(results), end="")
2025-07-02 06:41:16.317 - abcDefghiJkl
2025-07-02 06:41:16.317 + abcdefGhijkl
2025-07-02 06:41:16.317 """
2025-07-02 06:41:16.317
2025-07-02 06:41:16.317 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.317 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.317 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.317 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.317 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.318
2025-07-02 06:41:16.318 # search for the pair that matches best without being identical
2025-07-02 06:41:16.318 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.318 # on junk -- unless we have to)
2025-07-02 06:41:16.318 for j in range(blo, bhi):
2025-07-02 06:41:16.318 bj = b[j]
2025-07-02 06:41:16.318 cruncher.set_seq2(bj)
2025-07-02 06:41:16.318 for i in range(alo, ahi):
2025-07-02 06:41:16.318 ai = a[i]
2025-07-02 06:41:16.318 if ai == bj:
2025-07-02 06:41:16.318 if eqi is None:
2025-07-02 06:41:16.318 eqi, eqj = i, j
2025-07-02 06:41:16.318 continue
2025-07-02 06:41:16.318 cruncher.set_seq1(ai)
2025-07-02 06:41:16.318 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.318 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.318 # compares by a factor of 3.
2025-07-02 06:41:16.318 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.319 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.319 # of the computation is cached by cruncher
2025-07-02 06:41:16.319 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.319 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.319 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.319 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.319 if best_ratio < cutoff:
2025-07-02 06:41:16.319 # no non-identical "pretty close" pair
2025-07-02 06:41:16.319 if eqi is None:
2025-07-02 06:41:16.319 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.319 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.319 return
2025-07-02 06:41:16.319 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.319 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.319 else:
2025-07-02 06:41:16.319 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.319 eqi = None
2025-07-02 06:41:16.319
2025-07-02 06:41:16.320 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.320 # identical
2025-07-02 06:41:16.320
2025-07-02 06:41:16.320 # pump out diffs from before the synch point
2025-07-02 06:41:16.320 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.320
2025-07-02 06:41:16.320 # do intraline marking on the synch pair
2025-07-02 06:41:16.320 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.320 if eqi is None:
2025-07-02 06:41:16.320 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.320 atags = btags = ""
2025-07-02 06:41:16.320 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.320 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.320 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.320 if tag == 'replace':
2025-07-02 06:41:16.320 atags += '^' * la
2025-07-02 06:41:16.320 btags += '^' * lb
2025-07-02 06:41:16.320 elif tag == 'delete':
2025-07-02 06:41:16.320 atags += '-' * la
2025-07-02 06:41:16.320 elif tag == 'insert':
2025-07-02 06:41:16.321 btags += '+' * lb
2025-07-02 06:41:16.321 elif tag == 'equal':
2025-07-02 06:41:16.321 atags += ' ' * la
2025-07-02 06:41:16.321 btags += ' ' * lb
2025-07-02 06:41:16.321 else:
2025-07-02 06:41:16.321 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.321 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.321 else:
2025-07-02 06:41:16.321 # the synch pair is identical
2025-07-02 06:41:16.321 yield ' ' + aelt
2025-07-02 06:41:16.321
2025-07-02 06:41:16.321 # pump out diffs from after the synch point
2025-07-02 06:41:16.321 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.321
2025-07-02 06:41:16.321 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.321 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.321
2025-07-02 06:41:16.321 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.321 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.322 alo = 37, ahi = 1101
2025-07-02 06:41:16.322 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.322 blo = 37, bhi = 1101
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.322 g = []
2025-07-02 06:41:16.322 if alo < ahi:
2025-07-02 06:41:16.322 if blo < bhi:
2025-07-02 06:41:16.322 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.322 else:
2025-07-02 06:41:16.322 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.322 elif blo < bhi:
2025-07-02 06:41:16.322 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 > yield from g
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.322 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.323 alo = 37, ahi = 1101
2025-07-02 06:41:16.323 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.323 blo = 37, bhi = 1101
2025-07-02 06:41:16.323
2025-07-02 06:41:16.323 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.323 r"""
2025-07-02 06:41:16.323 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.323 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.323 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.323 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.323
2025-07-02 06:41:16.323 Example:
2025-07-02 06:41:16.323
2025-07-02 06:41:16.323 >>> d = Differ()
2025-07-02 06:41:16.323 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.323 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.323 >>> print(''.join(results), end="")
2025-07-02 06:41:16.323 - abcDefghiJkl
2025-07-02 06:41:16.324 + abcdefGhijkl
2025-07-02 06:41:16.324 """
2025-07-02 06:41:16.324
2025-07-02 06:41:16.324 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.324 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.324 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.324 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.324 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.324
2025-07-02 06:41:16.324 # search for the pair that matches best without being identical
2025-07-02 06:41:16.324 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.324 # on junk -- unless we have to)
2025-07-02 06:41:16.324 for j in range(blo, bhi):
2025-07-02 06:41:16.324 bj = b[j]
2025-07-02 06:41:16.324 cruncher.set_seq2(bj)
2025-07-02 06:41:16.324 for i in range(alo, ahi):
2025-07-02 06:41:16.324 ai = a[i]
2025-07-02 06:41:16.324 if ai == bj:
2025-07-02 06:41:16.325 if eqi is None:
2025-07-02 06:41:16.325 eqi, eqj = i, j
2025-07-02 06:41:16.325 continue
2025-07-02 06:41:16.325 cruncher.set_seq1(ai)
2025-07-02 06:41:16.325 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.325 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.325 # compares by a factor of 3.
2025-07-02 06:41:16.325 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.325 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.325 # of the computation is cached by cruncher
2025-07-02 06:41:16.325 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.325 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.325 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.325 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.325 if best_ratio < cutoff:
2025-07-02 06:41:16.325 # no non-identical "pretty close" pair
2025-07-02 06:41:16.325 if eqi is None:
2025-07-02 06:41:16.325 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.325 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.325 return
2025-07-02 06:41:16.326 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.326 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.326 else:
2025-07-02 06:41:16.326 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.326 eqi = None
2025-07-02 06:41:16.326
2025-07-02 06:41:16.326 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.326 # identical
2025-07-02 06:41:16.326
2025-07-02 06:41:16.326 # pump out diffs from before the synch point
2025-07-02 06:41:16.326 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.326
2025-07-02 06:41:16.326 # do intraline marking on the synch pair
2025-07-02 06:41:16.326 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.326 if eqi is None:
2025-07-02 06:41:16.326 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.326 atags = btags = ""
2025-07-02 06:41:16.326 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.326 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.326 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.327 if tag == 'replace':
2025-07-02 06:41:16.327 atags += '^' * la
2025-07-02 06:41:16.327 btags += '^' * lb
2025-07-02 06:41:16.327 elif tag == 'delete':
2025-07-02 06:41:16.327 atags += '-' * la
2025-07-02 06:41:16.327 elif tag == 'insert':
2025-07-02 06:41:16.327 btags += '+' * lb
2025-07-02 06:41:16.327 elif tag == 'equal':
2025-07-02 06:41:16.327 atags += ' ' * la
2025-07-02 06:41:16.327 btags += ' ' * lb
2025-07-02 06:41:16.327 else:
2025-07-02 06:41:16.327 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.327 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.327 else:
2025-07-02 06:41:16.327 # the synch pair is identical
2025-07-02 06:41:16.327 yield ' ' + aelt
2025-07-02 06:41:16.327
2025-07-02 06:41:16.327 # pump out diffs from after the synch point
2025-07-02 06:41:16.327 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.328
2025-07-02 06:41:16.328 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.328 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.328
2025-07-02 06:41:16.328 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.328 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.328 alo = 38, ahi = 1101
2025-07-02 06:41:16.328 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.328 blo = 38, bhi = 1101
2025-07-02 06:41:16.328
2025-07-02 06:41:16.328 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.328 g = []
2025-07-02 06:41:16.328 if alo < ahi:
2025-07-02 06:41:16.328 if blo < bhi:
2025-07-02 06:41:16.328 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.328 else:
2025-07-02 06:41:16.328 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.328 elif blo < bhi:
2025-07-02 06:41:16.329 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 > yield from g
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.329 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.329 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.329 alo = 38, ahi = 1101
2025-07-02 06:41:16.329 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.329 blo = 38, bhi = 1101
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.329 r"""
2025-07-02 06:41:16.329 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.329 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.329 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.329 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330 Example:
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330 >>> d = Differ()
2025-07-02 06:41:16.330 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.330 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.330 >>> print(''.join(results), end="")
2025-07-02 06:41:16.330 - abcDefghiJkl
2025-07-02 06:41:16.330 + abcdefGhijkl
2025-07-02 06:41:16.330 """
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.330 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.330 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.330 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.330 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330 # search for the pair that matches best without being identical
2025-07-02 06:41:16.331 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.331 # on junk -- unless we have to)
2025-07-02 06:41:16.331 for j in range(blo, bhi):
2025-07-02 06:41:16.331 bj = b[j]
2025-07-02 06:41:16.331 cruncher.set_seq2(bj)
2025-07-02 06:41:16.331 for i in range(alo, ahi):
2025-07-02 06:41:16.331 ai = a[i]
2025-07-02 06:41:16.331 if ai == bj:
2025-07-02 06:41:16.331 if eqi is None:
2025-07-02 06:41:16.331 eqi, eqj = i, j
2025-07-02 06:41:16.331 continue
2025-07-02 06:41:16.331 cruncher.set_seq1(ai)
2025-07-02 06:41:16.331 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.331 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.331 # compares by a factor of 3.
2025-07-02 06:41:16.331 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.331 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.331 # of the computation is cached by cruncher
2025-07-02 06:41:16.331 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.331 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.331 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.332 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.332 if best_ratio < cutoff:
2025-07-02 06:41:16.332 # no non-identical "pretty close" pair
2025-07-02 06:41:16.332 if eqi is None:
2025-07-02 06:41:16.332 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.332 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.332 return
2025-07-02 06:41:16.332 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.332 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.332 else:
2025-07-02 06:41:16.332 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.332 eqi = None
2025-07-02 06:41:16.332
2025-07-02 06:41:16.332 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.332 # identical
2025-07-02 06:41:16.332
2025-07-02 06:41:16.332 # pump out diffs from before the synch point
2025-07-02 06:41:16.332 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.332
2025-07-02 06:41:16.332 # do intraline marking on the synch pair
2025-07-02 06:41:16.333 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.333 if eqi is None:
2025-07-02 06:41:16.333 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.333 atags = btags = ""
2025-07-02 06:41:16.333 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.333 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.333 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.333 if tag == 'replace':
2025-07-02 06:41:16.333 atags += '^' * la
2025-07-02 06:41:16.333 btags += '^' * lb
2025-07-02 06:41:16.333 elif tag == 'delete':
2025-07-02 06:41:16.333 atags += '-' * la
2025-07-02 06:41:16.333 elif tag == 'insert':
2025-07-02 06:41:16.333 btags += '+' * lb
2025-07-02 06:41:16.333 elif tag == 'equal':
2025-07-02 06:41:16.333 atags += ' ' * la
2025-07-02 06:41:16.333 btags += ' ' * lb
2025-07-02 06:41:16.333 else:
2025-07-02 06:41:16.333 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.333 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.333 else:
2025-07-02 06:41:16.334 # the synch pair is identical
2025-07-02 06:41:16.334 yield ' ' + aelt
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334 # pump out diffs from after the synch point
2025-07-02 06:41:16.334 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.334 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.334 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.334 alo = 39, ahi = 1101
2025-07-02 06:41:16.334 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.334 blo = 39, bhi = 1101
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.334 g = []
2025-07-02 06:41:16.334 if alo < ahi:
2025-07-02 06:41:16.335 if blo < bhi:
2025-07-02 06:41:16.335 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.335 else:
2025-07-02 06:41:16.335 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.335 elif blo < bhi:
2025-07-02 06:41:16.335 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 > yield from g
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.335 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.335 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.335 alo = 39, ahi = 1101
2025-07-02 06:41:16.335 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.335 blo = 39, bhi = 1101
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.335 r"""
2025-07-02 06:41:16.336 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.336 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.336 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.336 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.336
2025-07-02 06:41:16.336 Example:
2025-07-02 06:41:16.336
2025-07-02 06:41:16.336 >>> d = Differ()
2025-07-02 06:41:16.336 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.336 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.336 >>> print(''.join(results), end="")
2025-07-02 06:41:16.336 - abcDefghiJkl
2025-07-02 06:41:16.336 + abcdefGhijkl
2025-07-02 06:41:16.336 """
2025-07-02 06:41:16.336
2025-07-02 06:41:16.337 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.337 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.337 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.337 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.337 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.337
2025-07-02 06:41:16.337 # search for the pair that matches best without being identical
2025-07-02 06:41:16.337 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.337 # on junk -- unless we have to)
2025-07-02 06:41:16.337 for j in range(blo, bhi):
2025-07-02 06:41:16.337 bj = b[j]
2025-07-02 06:41:16.337 cruncher.set_seq2(bj)
2025-07-02 06:41:16.337 for i in range(alo, ahi):
2025-07-02 06:41:16.337 ai = a[i]
2025-07-02 06:41:16.337 if ai == bj:
2025-07-02 06:41:16.337 if eqi is None:
2025-07-02 06:41:16.337 eqi, eqj = i, j
2025-07-02 06:41:16.337 continue
2025-07-02 06:41:16.337 cruncher.set_seq1(ai)
2025-07-02 06:41:16.338 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.338 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.338 # compares by a factor of 3.
2025-07-02 06:41:16.338 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.338 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.338 # of the computation is cached by cruncher
2025-07-02 06:41:16.338 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.338 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.338 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.338 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.338 if best_ratio < cutoff:
2025-07-02 06:41:16.338 # no non-identical "pretty close" pair
2025-07-02 06:41:16.338 if eqi is None:
2025-07-02 06:41:16.338 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.338 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.338 return
2025-07-02 06:41:16.338 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.338 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.338 else:
2025-07-02 06:41:16.338 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.338 eqi = None
2025-07-02 06:41:16.339
2025-07-02 06:41:16.339 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.339 # identical
2025-07-02 06:41:16.339
2025-07-02 06:41:16.339 # pump out diffs from before the synch point
2025-07-02 06:41:16.339 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.339
2025-07-02 06:41:16.339 # do intraline marking on the synch pair
2025-07-02 06:41:16.339 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.339 if eqi is None:
2025-07-02 06:41:16.339 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.339 atags = btags = ""
2025-07-02 06:41:16.339 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.339 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.339 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.339 if tag == 'replace':
2025-07-02 06:41:16.339 atags += '^' * la
2025-07-02 06:41:16.339 btags += '^' * lb
2025-07-02 06:41:16.339 elif tag == 'delete':
2025-07-02 06:41:16.339 atags += '-' * la
2025-07-02 06:41:16.340 elif tag == 'insert':
2025-07-02 06:41:16.340 btags += '+' * lb
2025-07-02 06:41:16.340 elif tag == 'equal':
2025-07-02 06:41:16.340 atags += ' ' * la
2025-07-02 06:41:16.340 btags += ' ' * lb
2025-07-02 06:41:16.340 else:
2025-07-02 06:41:16.340 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.340 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.340 else:
2025-07-02 06:41:16.340 # the synch pair is identical
2025-07-02 06:41:16.340 yield ' ' + aelt
2025-07-02 06:41:16.340
2025-07-02 06:41:16.340 # pump out diffs from after the synch point
2025-07-02 06:41:16.340 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.340
2025-07-02 06:41:16.340 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.340 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.340
2025-07-02 06:41:16.340 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.340 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.341 alo = 40, ahi = 1101
2025-07-02 06:41:16.341 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.341 blo = 40, bhi = 1101
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.341 g = []
2025-07-02 06:41:16.341 if alo < ahi:
2025-07-02 06:41:16.341 if blo < bhi:
2025-07-02 06:41:16.341 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.341 else:
2025-07-02 06:41:16.341 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.341 elif blo < bhi:
2025-07-02 06:41:16.341 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 > yield from g
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.341 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.341 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.342 alo = 40, ahi = 1101
2025-07-02 06:41:16.342 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.342 blo = 40, bhi = 1101
2025-07-02 06:41:16.342
2025-07-02 06:41:16.342 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.342 r"""
2025-07-02 06:41:16.342 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.342 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.342 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.342 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.342
2025-07-02 06:41:16.342 Example:
2025-07-02 06:41:16.342
2025-07-02 06:41:16.342 >>> d = Differ()
2025-07-02 06:41:16.342 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.342 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.342 >>> print(''.join(results), end="")
2025-07-02 06:41:16.342 - abcDefghiJkl
2025-07-02 06:41:16.342 + abcdefGhijkl
2025-07-02 06:41:16.343 """
2025-07-02 06:41:16.343
2025-07-02 06:41:16.343 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.343 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.343 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.343 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.343 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.343
2025-07-02 06:41:16.343 # search for the pair that matches best without being identical
2025-07-02 06:41:16.343 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.343 # on junk -- unless we have to)
2025-07-02 06:41:16.343 for j in range(blo, bhi):
2025-07-02 06:41:16.343 bj = b[j]
2025-07-02 06:41:16.343 cruncher.set_seq2(bj)
2025-07-02 06:41:16.343 for i in range(alo, ahi):
2025-07-02 06:41:16.343 ai = a[i]
2025-07-02 06:41:16.343 if ai == bj:
2025-07-02 06:41:16.343 if eqi is None:
2025-07-02 06:41:16.343 eqi, eqj = i, j
2025-07-02 06:41:16.344 continue
2025-07-02 06:41:16.344 cruncher.set_seq1(ai)
2025-07-02 06:41:16.344 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.344 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.344 # compares by a factor of 3.
2025-07-02 06:41:16.344 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.344 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.344 # of the computation is cached by cruncher
2025-07-02 06:41:16.344 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.344 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.344 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.344 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.344 if best_ratio < cutoff:
2025-07-02 06:41:16.344 # no non-identical "pretty close" pair
2025-07-02 06:41:16.344 if eqi is None:
2025-07-02 06:41:16.344 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.344 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.344 return
2025-07-02 06:41:16.345 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.345 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.345 else:
2025-07-02 06:41:16.345 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.345 eqi = None
2025-07-02 06:41:16.345
2025-07-02 06:41:16.345 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.345 # identical
2025-07-02 06:41:16.345
2025-07-02 06:41:16.345 # pump out diffs from before the synch point
2025-07-02 06:41:16.345 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.345
2025-07-02 06:41:16.345 # do intraline marking on the synch pair
2025-07-02 06:41:16.345 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.345 if eqi is None:
2025-07-02 06:41:16.345 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.345 atags = btags = ""
2025-07-02 06:41:16.345 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.345 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.345 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.346 if tag == 'replace':
2025-07-02 06:41:16.346 atags += '^' * la
2025-07-02 06:41:16.346 btags += '^' * lb
2025-07-02 06:41:16.346 elif tag == 'delete':
2025-07-02 06:41:16.346 atags += '-' * la
2025-07-02 06:41:16.346 elif tag == 'insert':
2025-07-02 06:41:16.346 btags += '+' * lb
2025-07-02 06:41:16.346 elif tag == 'equal':
2025-07-02 06:41:16.346 atags += ' ' * la
2025-07-02 06:41:16.346 btags += ' ' * lb
2025-07-02 06:41:16.346 else:
2025-07-02 06:41:16.346 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.346 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.346 else:
2025-07-02 06:41:16.346 # the synch pair is identical
2025-07-02 06:41:16.346 yield ' ' + aelt
2025-07-02 06:41:16.346
2025-07-02 06:41:16.346 # pump out diffs from after the synch point
2025-07-02 06:41:16.346 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.346
2025-07-02 06:41:16.347 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.347 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.347
2025-07-02 06:41:16.347 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.347 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.347 alo = 41, ahi = 1101
2025-07-02 06:41:16.347 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.347 blo = 41, bhi = 1101
2025-07-02 06:41:16.347
2025-07-02 06:41:16.347 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.347 g = []
2025-07-02 06:41:16.347 if alo < ahi:
2025-07-02 06:41:16.347 if blo < bhi:
2025-07-02 06:41:16.347 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.347 else:
2025-07-02 06:41:16.347 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.347 elif blo < bhi:
2025-07-02 06:41:16.347 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.347
2025-07-02 06:41:16.347 > yield from g
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.348 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.348 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.348 alo = 41, ahi = 1101
2025-07-02 06:41:16.348 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.348 blo = 41, bhi = 1101
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.348 r"""
2025-07-02 06:41:16.348 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.348 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.348 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.348 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 Example:
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 >>> d = Differ()
2025-07-02 06:41:16.349 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.349 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.349 >>> print(''.join(results), end="")
2025-07-02 06:41:16.349 - abcDefghiJkl
2025-07-02 06:41:16.349 + abcdefGhijkl
2025-07-02 06:41:16.349 """
2025-07-02 06:41:16.349
2025-07-02 06:41:16.349 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.349 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.349 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.349 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.349 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.349
2025-07-02 06:41:16.349 # search for the pair that matches best without being identical
2025-07-02 06:41:16.349 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.349 # on junk -- unless we have to)
2025-07-02 06:41:16.349 for j in range(blo, bhi):
2025-07-02 06:41:16.349 bj = b[j]
2025-07-02 06:41:16.350 cruncher.set_seq2(bj)
2025-07-02 06:41:16.350 for i in range(alo, ahi):
2025-07-02 06:41:16.350 ai = a[i]
2025-07-02 06:41:16.350 if ai == bj:
2025-07-02 06:41:16.350 if eqi is None:
2025-07-02 06:41:16.350 eqi, eqj = i, j
2025-07-02 06:41:16.350 continue
2025-07-02 06:41:16.350 cruncher.set_seq1(ai)
2025-07-02 06:41:16.350 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.350 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.350 # compares by a factor of 3.
2025-07-02 06:41:16.350 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.350 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.350 # of the computation is cached by cruncher
2025-07-02 06:41:16.350 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.350 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.350 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.350 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.351 if best_ratio < cutoff:
2025-07-02 06:41:16.351 # no non-identical "pretty close" pair
2025-07-02 06:41:16.351 if eqi is None:
2025-07-02 06:41:16.351 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.351 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.351 return
2025-07-02 06:41:16.351 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.351 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.351 else:
2025-07-02 06:41:16.351 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.351 eqi = None
2025-07-02 06:41:16.351
2025-07-02 06:41:16.351 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.351 # identical
2025-07-02 06:41:16.351
2025-07-02 06:41:16.351 # pump out diffs from before the synch point
2025-07-02 06:41:16.351 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.351
2025-07-02 06:41:16.351 # do intraline marking on the synch pair
2025-07-02 06:41:16.352 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.352 if eqi is None:
2025-07-02 06:41:16.352 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.352 atags = btags = ""
2025-07-02 06:41:16.352 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.352 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.352 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.352 if tag == 'replace':
2025-07-02 06:41:16.352 atags += '^' * la
2025-07-02 06:41:16.352 btags += '^' * lb
2025-07-02 06:41:16.352 elif tag == 'delete':
2025-07-02 06:41:16.352 atags += '-' * la
2025-07-02 06:41:16.352 elif tag == 'insert':
2025-07-02 06:41:16.352 btags += '+' * lb
2025-07-02 06:41:16.352 elif tag == 'equal':
2025-07-02 06:41:16.352 atags += ' ' * la
2025-07-02 06:41:16.352 btags += ' ' * lb
2025-07-02 06:41:16.352 else:
2025-07-02 06:41:16.352 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.353 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.353 else:
2025-07-02 06:41:16.353 # the synch pair is identical
2025-07-02 06:41:16.353 yield ' ' + aelt
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353 # pump out diffs from after the synch point
2025-07-02 06:41:16.353 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.353 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.353 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.353 alo = 42, ahi = 1101
2025-07-02 06:41:16.353 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.353 blo = 42, bhi = 1101
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.354 g = []
2025-07-02 06:41:16.354 if alo < ahi:
2025-07-02 06:41:16.354 if blo < bhi:
2025-07-02 06:41:16.354 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.354 else:
2025-07-02 06:41:16.354 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.354 elif blo < bhi:
2025-07-02 06:41:16.354 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.354
2025-07-02 06:41:16.354 > yield from g
2025-07-02 06:41:16.354
2025-07-02 06:41:16.354 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.354 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.354
2025-07-02 06:41:16.354 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.354 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.354 alo = 42, ahi = 1101
2025-07-02 06:41:16.354 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.354 blo = 42, bhi = 1101
2025-07-02 06:41:16.355
2025-07-02 06:41:16.355 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.355 r"""
2025-07-02 06:41:16.355 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.355 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.355 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.355 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.355
2025-07-02 06:41:16.355 Example:
2025-07-02 06:41:16.355
2025-07-02 06:41:16.355 >>> d = Differ()
2025-07-02 06:41:16.355 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.355 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.355 >>> print(''.join(results), end="")
2025-07-02 06:41:16.355 - abcDefghiJkl
2025-07-02 06:41:16.355 + abcdefGhijkl
2025-07-02 06:41:16.355 """
2025-07-02 06:41:16.355
2025-07-02 06:41:16.356 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.356 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.356 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.356 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.356 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.356
2025-07-02 06:41:16.356 # search for the pair that matches best without being identical
2025-07-02 06:41:16.356 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.356 # on junk -- unless we have to)
2025-07-02 06:41:16.356 for j in range(blo, bhi):
2025-07-02 06:41:16.356 bj = b[j]
2025-07-02 06:41:16.356 cruncher.set_seq2(bj)
2025-07-02 06:41:16.356 for i in range(alo, ahi):
2025-07-02 06:41:16.356 ai = a[i]
2025-07-02 06:41:16.356 if ai == bj:
2025-07-02 06:41:16.356 if eqi is None:
2025-07-02 06:41:16.356 eqi, eqj = i, j
2025-07-02 06:41:16.356 continue
2025-07-02 06:41:16.356 cruncher.set_seq1(ai)
2025-07-02 06:41:16.356 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.356 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.357 # compares by a factor of 3.
2025-07-02 06:41:16.357 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.357 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.357 # of the computation is cached by cruncher
2025-07-02 06:41:16.357 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.357 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.357 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.357 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.357 if best_ratio < cutoff:
2025-07-02 06:41:16.357 # no non-identical "pretty close" pair
2025-07-02 06:41:16.357 if eqi is None:
2025-07-02 06:41:16.357 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.357 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.357 return
2025-07-02 06:41:16.357 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.357 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.357 else:
2025-07-02 06:41:16.357 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.357 eqi = None
2025-07-02 06:41:16.357
2025-07-02 06:41:16.358 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.358 # identical
2025-07-02 06:41:16.358
2025-07-02 06:41:16.358 # pump out diffs from before the synch point
2025-07-02 06:41:16.358 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.358
2025-07-02 06:41:16.358 # do intraline marking on the synch pair
2025-07-02 06:41:16.358 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.358 if eqi is None:
2025-07-02 06:41:16.358 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.358 atags = btags = ""
2025-07-02 06:41:16.358 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.358 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.358 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.358 if tag == 'replace':
2025-07-02 06:41:16.358 atags += '^' * la
2025-07-02 06:41:16.358 btags += '^' * lb
2025-07-02 06:41:16.358 elif tag == 'delete':
2025-07-02 06:41:16.358 atags += '-' * la
2025-07-02 06:41:16.358 elif tag == 'insert':
2025-07-02 06:41:16.359 btags += '+' * lb
2025-07-02 06:41:16.359 elif tag == 'equal':
2025-07-02 06:41:16.359 atags += ' ' * la
2025-07-02 06:41:16.359 btags += ' ' * lb
2025-07-02 06:41:16.359 else:
2025-07-02 06:41:16.359 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.359 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.359 else:
2025-07-02 06:41:16.359 # the synch pair is identical
2025-07-02 06:41:16.359 yield ' ' + aelt
2025-07-02 06:41:16.359
2025-07-02 06:41:16.359 # pump out diffs from after the synch point
2025-07-02 06:41:16.359 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.359
2025-07-02 06:41:16.359 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.359 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.359
2025-07-02 06:41:16.359 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.359 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.359 alo = 43, ahi = 1101
2025-07-02 06:41:16.359 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.360 blo = 43, bhi = 1101
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.360 g = []
2025-07-02 06:41:16.360 if alo < ahi:
2025-07-02 06:41:16.360 if blo < bhi:
2025-07-02 06:41:16.360 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.360 else:
2025-07-02 06:41:16.360 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.360 elif blo < bhi:
2025-07-02 06:41:16.360 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 > yield from g
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.360 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.360 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.360 alo = 43, ahi = 1101
2025-07-02 06:41:16.361 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.361 blo = 43, bhi = 1101
2025-07-02 06:41:16.361
2025-07-02 06:41:16.361 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.361 r"""
2025-07-02 06:41:16.361 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.361 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.361 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.361 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.361
2025-07-02 06:41:16.361 Example:
2025-07-02 06:41:16.361
2025-07-02 06:41:16.361 >>> d = Differ()
2025-07-02 06:41:16.361 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.361 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.361 >>> print(''.join(results), end="")
2025-07-02 06:41:16.361 - abcDefghiJkl
2025-07-02 06:41:16.361 + abcdefGhijkl
2025-07-02 06:41:16.362 """
2025-07-02 06:41:16.362
2025-07-02 06:41:16.362 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.362 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.362 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.362 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.362 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.362
2025-07-02 06:41:16.362 # search for the pair that matches best without being identical
2025-07-02 06:41:16.362 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.362 # on junk -- unless we have to)
2025-07-02 06:41:16.362 for j in range(blo, bhi):
2025-07-02 06:41:16.362 bj = b[j]
2025-07-02 06:41:16.362 cruncher.set_seq2(bj)
2025-07-02 06:41:16.362 for i in range(alo, ahi):
2025-07-02 06:41:16.362 ai = a[i]
2025-07-02 06:41:16.362 if ai == bj:
2025-07-02 06:41:16.362 if eqi is None:
2025-07-02 06:41:16.362 eqi, eqj = i, j
2025-07-02 06:41:16.363 continue
2025-07-02 06:41:16.363 cruncher.set_seq1(ai)
2025-07-02 06:41:16.363 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.363 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.363 # compares by a factor of 3.
2025-07-02 06:41:16.363 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.363 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.363 # of the computation is cached by cruncher
2025-07-02 06:41:16.363 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.363 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.363 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.363 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.363 if best_ratio < cutoff:
2025-07-02 06:41:16.363 # no non-identical "pretty close" pair
2025-07-02 06:41:16.363 if eqi is None:
2025-07-02 06:41:16.363 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.363 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.363 return
2025-07-02 06:41:16.363 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.364 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.364 else:
2025-07-02 06:41:16.364 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.364 eqi = None
2025-07-02 06:41:16.364
2025-07-02 06:41:16.364 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.364 # identical
2025-07-02 06:41:16.364
2025-07-02 06:41:16.364 # pump out diffs from before the synch point
2025-07-02 06:41:16.364 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.364
2025-07-02 06:41:16.364 # do intraline marking on the synch pair
2025-07-02 06:41:16.364 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.364 if eqi is None:
2025-07-02 06:41:16.364 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.364 atags = btags = ""
2025-07-02 06:41:16.364 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.364 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.364 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.364 if tag == 'replace':
2025-07-02 06:41:16.365 atags += '^' * la
2025-07-02 06:41:16.365 btags += '^' * lb
2025-07-02 06:41:16.365 elif tag == 'delete':
2025-07-02 06:41:16.365 atags += '-' * la
2025-07-02 06:41:16.365 elif tag == 'insert':
2025-07-02 06:41:16.365 btags += '+' * lb
2025-07-02 06:41:16.365 elif tag == 'equal':
2025-07-02 06:41:16.365 atags += ' ' * la
2025-07-02 06:41:16.365 btags += ' ' * lb
2025-07-02 06:41:16.365 else:
2025-07-02 06:41:16.365 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.365 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.365 else:
2025-07-02 06:41:16.365 # the synch pair is identical
2025-07-02 06:41:16.365 yield ' ' + aelt
2025-07-02 06:41:16.365
2025-07-02 06:41:16.365 # pump out diffs from after the synch point
2025-07-02 06:41:16.365 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.365
2025-07-02 06:41:16.365 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.365 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.366
2025-07-02 06:41:16.366 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.366 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.366 alo = 44, ahi = 1101
2025-07-02 06:41:16.366 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.366 blo = 44, bhi = 1101
2025-07-02 06:41:16.366
2025-07-02 06:41:16.366 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.366 g = []
2025-07-02 06:41:16.366 if alo < ahi:
2025-07-02 06:41:16.366 if blo < bhi:
2025-07-02 06:41:16.366 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.366 else:
2025-07-02 06:41:16.366 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.366 elif blo < bhi:
2025-07-02 06:41:16.366 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.366
2025-07-02 06:41:16.367 > yield from g
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.367 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.367 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.367 alo = 44, ahi = 1101
2025-07-02 06:41:16.367 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.367 blo = 44, bhi = 1101
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.367 r"""
2025-07-02 06:41:16.367 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.367 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.367 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.367 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367 Example:
2025-07-02 06:41:16.368
2025-07-02 06:41:16.368 >>> d = Differ()
2025-07-02 06:41:16.368 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.368 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.368 >>> print(''.join(results), end="")
2025-07-02 06:41:16.368 - abcDefghiJkl
2025-07-02 06:41:16.368 + abcdefGhijkl
2025-07-02 06:41:16.368 """
2025-07-02 06:41:16.368
2025-07-02 06:41:16.368 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.368 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.368 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.368 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.368 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.368
2025-07-02 06:41:16.368 # search for the pair that matches best without being identical
2025-07-02 06:41:16.368 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.368 # on junk -- unless we have to)
2025-07-02 06:41:16.369 for j in range(blo, bhi):
2025-07-02 06:41:16.369 bj = b[j]
2025-07-02 06:41:16.369 cruncher.set_seq2(bj)
2025-07-02 06:41:16.369 for i in range(alo, ahi):
2025-07-02 06:41:16.369 ai = a[i]
2025-07-02 06:41:16.369 if ai == bj:
2025-07-02 06:41:16.369 if eqi is None:
2025-07-02 06:41:16.369 eqi, eqj = i, j
2025-07-02 06:41:16.369 continue
2025-07-02 06:41:16.369 cruncher.set_seq1(ai)
2025-07-02 06:41:16.369 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.369 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.369 # compares by a factor of 3.
2025-07-02 06:41:16.369 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.369 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.369 # of the computation is cached by cruncher
2025-07-02 06:41:16.369 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.369 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.369 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.369 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.370 if best_ratio < cutoff:
2025-07-02 06:41:16.370 # no non-identical "pretty close" pair
2025-07-02 06:41:16.370 if eqi is None:
2025-07-02 06:41:16.370 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.370 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.370 return
2025-07-02 06:41:16.370 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.370 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.370 else:
2025-07-02 06:41:16.370 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.370 eqi = None
2025-07-02 06:41:16.370
2025-07-02 06:41:16.370 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.370 # identical
2025-07-02 06:41:16.370
2025-07-02 06:41:16.370 # pump out diffs from before the synch point
2025-07-02 06:41:16.370 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.370
2025-07-02 06:41:16.370 # do intraline marking on the synch pair
2025-07-02 06:41:16.370 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.371 if eqi is None:
2025-07-02 06:41:16.371 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.371 atags = btags = ""
2025-07-02 06:41:16.371 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.371 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.371 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.371 if tag == 'replace':
2025-07-02 06:41:16.371 atags += '^' * la
2025-07-02 06:41:16.371 btags += '^' * lb
2025-07-02 06:41:16.371 elif tag == 'delete':
2025-07-02 06:41:16.371 atags += '-' * la
2025-07-02 06:41:16.371 elif tag == 'insert':
2025-07-02 06:41:16.371 btags += '+' * lb
2025-07-02 06:41:16.371 elif tag == 'equal':
2025-07-02 06:41:16.371 atags += ' ' * la
2025-07-02 06:41:16.371 btags += ' ' * lb
2025-07-02 06:41:16.371 else:
2025-07-02 06:41:16.371 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.372 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.372 else:
2025-07-02 06:41:16.372 # the synch pair is identical
2025-07-02 06:41:16.372 yield ' ' + aelt
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372 # pump out diffs from after the synch point
2025-07-02 06:41:16.372 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.372 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.372 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.372 alo = 45, ahi = 1101
2025-07-02 06:41:16.372 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.372 blo = 45, bhi = 1101
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.372 g = []
2025-07-02 06:41:16.372 if alo < ahi:
2025-07-02 06:41:16.373 if blo < bhi:
2025-07-02 06:41:16.373 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.373 else:
2025-07-02 06:41:16.373 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.373 elif blo < bhi:
2025-07-02 06:41:16.373 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 > yield from g
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.373 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.373 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.373 alo = 45, ahi = 1101
2025-07-02 06:41:16.373 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.373 blo = 45, bhi = 1101
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.374 r"""
2025-07-02 06:41:16.374 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.374 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.374 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.374 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.374
2025-07-02 06:41:16.374 Example:
2025-07-02 06:41:16.374
2025-07-02 06:41:16.374 >>> d = Differ()
2025-07-02 06:41:16.374 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.374 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.374 >>> print(''.join(results), end="")
2025-07-02 06:41:16.374 - abcDefghiJkl
2025-07-02 06:41:16.374 + abcdefGhijkl
2025-07-02 06:41:16.374 """
2025-07-02 06:41:16.374
2025-07-02 06:41:16.374 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.374 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.375 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.375 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.375 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.375
2025-07-02 06:41:16.375 # search for the pair that matches best without being identical
2025-07-02 06:41:16.375 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.375 # on junk -- unless we have to)
2025-07-02 06:41:16.375 for j in range(blo, bhi):
2025-07-02 06:41:16.375 bj = b[j]
2025-07-02 06:41:16.375 cruncher.set_seq2(bj)
2025-07-02 06:41:16.375 for i in range(alo, ahi):
2025-07-02 06:41:16.375 ai = a[i]
2025-07-02 06:41:16.375 if ai == bj:
2025-07-02 06:41:16.375 if eqi is None:
2025-07-02 06:41:16.375 eqi, eqj = i, j
2025-07-02 06:41:16.375 continue
2025-07-02 06:41:16.375 cruncher.set_seq1(ai)
2025-07-02 06:41:16.375 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.375 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.375 # compares by a factor of 3.
2025-07-02 06:41:16.375 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.376 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.376 # of the computation is cached by cruncher
2025-07-02 06:41:16.376 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.376 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.376 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.376 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.376 if best_ratio < cutoff:
2025-07-02 06:41:16.376 # no non-identical "pretty close" pair
2025-07-02 06:41:16.376 if eqi is None:
2025-07-02 06:41:16.376 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.376 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.376 return
2025-07-02 06:41:16.376 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.376 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.376 else:
2025-07-02 06:41:16.376 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.376 eqi = None
2025-07-02 06:41:16.376
2025-07-02 06:41:16.376 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.376 # identical
2025-07-02 06:41:16.377
2025-07-02 06:41:16.377 # pump out diffs from before the synch point
2025-07-02 06:41:16.377 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.377
2025-07-02 06:41:16.377 # do intraline marking on the synch pair
2025-07-02 06:41:16.377 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.377 if eqi is None:
2025-07-02 06:41:16.377 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.377 atags = btags = ""
2025-07-02 06:41:16.377 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.377 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.377 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.377 if tag == 'replace':
2025-07-02 06:41:16.377 atags += '^' * la
2025-07-02 06:41:16.377 btags += '^' * lb
2025-07-02 06:41:16.377 elif tag == 'delete':
2025-07-02 06:41:16.377 atags += '-' * la
2025-07-02 06:41:16.377 elif tag == 'insert':
2025-07-02 06:41:16.377 btags += '+' * lb
2025-07-02 06:41:16.377 elif tag == 'equal':
2025-07-02 06:41:16.377 atags += ' ' * la
2025-07-02 06:41:16.378 btags += ' ' * lb
2025-07-02 06:41:16.378 else:
2025-07-02 06:41:16.378 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.378 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.378 else:
2025-07-02 06:41:16.378 # the synch pair is identical
2025-07-02 06:41:16.378 yield ' ' + aelt
2025-07-02 06:41:16.378
2025-07-02 06:41:16.378 # pump out diffs from after the synch point
2025-07-02 06:41:16.378 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.378
2025-07-02 06:41:16.378 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.378 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.378
2025-07-02 06:41:16.378 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.378 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.378 alo = 48, ahi = 1101
2025-07-02 06:41:16.378 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.378 blo = 48, bhi = 1101
2025-07-02 06:41:16.378
2025-07-02 06:41:16.379 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.379 g = []
2025-07-02 06:41:16.379 if alo < ahi:
2025-07-02 06:41:16.379 if blo < bhi:
2025-07-02 06:41:16.379 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.379 else:
2025-07-02 06:41:16.379 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.379 elif blo < bhi:
2025-07-02 06:41:16.379 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 > yield from g
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.379 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.379 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.379 alo = 48, ahi = 1101
2025-07-02 06:41:16.379 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.379 blo = 48, bhi = 1101
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.379 r"""
2025-07-02 06:41:16.379 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.379 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.379 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.379 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 Example:
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 >>> d = Differ()
2025-07-02 06:41:16.379 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.380 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.380 >>> print(''.join(results), end="")
2025-07-02 06:41:16.380 - abcDefghiJkl
2025-07-02 06:41:16.380 + abcdefGhijkl
2025-07-02 06:41:16.380 """
2025-07-02 06:41:16.380
2025-07-02 06:41:16.380 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.380 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.380 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.380 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.380 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.380
2025-07-02 06:41:16.380 # search for the pair that matches best without being identical
2025-07-02 06:41:16.380 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.380 # on junk -- unless we have to)
2025-07-02 06:41:16.380 for j in range(blo, bhi):
2025-07-02 06:41:16.380 bj = b[j]
2025-07-02 06:41:16.381 cruncher.set_seq2(bj)
2025-07-02 06:41:16.381 for i in range(alo, ahi):
2025-07-02 06:41:16.381 ai = a[i]
2025-07-02 06:41:16.381 if ai == bj:
2025-07-02 06:41:16.381 if eqi is None:
2025-07-02 06:41:16.381 eqi, eqj = i, j
2025-07-02 06:41:16.381 continue
2025-07-02 06:41:16.381 cruncher.set_seq1(ai)
2025-07-02 06:41:16.381 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.381 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.381 # compares by a factor of 3.
2025-07-02 06:41:16.381 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.381 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.381 # of the computation is cached by cruncher
2025-07-02 06:41:16.381 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.381 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.381 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.381 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.382 if best_ratio < cutoff:
2025-07-02 06:41:16.382 # no non-identical "pretty close" pair
2025-07-02 06:41:16.382 if eqi is None:
2025-07-02 06:41:16.382 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.382 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.382 return
2025-07-02 06:41:16.382 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.382 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.382 else:
2025-07-02 06:41:16.382 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.382 eqi = None
2025-07-02 06:41:16.382
2025-07-02 06:41:16.382 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.382 # identical
2025-07-02 06:41:16.382
2025-07-02 06:41:16.382 # pump out diffs from before the synch point
2025-07-02 06:41:16.382 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.382
2025-07-02 06:41:16.382 # do intraline marking on the synch pair
2025-07-02 06:41:16.382 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.382 if eqi is None:
2025-07-02 06:41:16.383 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.383 atags = btags = ""
2025-07-02 06:41:16.383 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.383 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.383 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.383 if tag == 'replace':
2025-07-02 06:41:16.383 atags += '^' * la
2025-07-02 06:41:16.383 btags += '^' * lb
2025-07-02 06:41:16.383 elif tag == 'delete':
2025-07-02 06:41:16.383 atags += '-' * la
2025-07-02 06:41:16.383 elif tag == 'insert':
2025-07-02 06:41:16.383 btags += '+' * lb
2025-07-02 06:41:16.383 elif tag == 'equal':
2025-07-02 06:41:16.383 atags += ' ' * la
2025-07-02 06:41:16.383 btags += ' ' * lb
2025-07-02 06:41:16.383 else:
2025-07-02 06:41:16.383 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.383 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.383 else:
2025-07-02 06:41:16.383 # the synch pair is identical
2025-07-02 06:41:16.384 yield ' ' + aelt
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384 # pump out diffs from after the synch point
2025-07-02 06:41:16.384 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.384 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.384 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.384 alo = 49, ahi = 1101
2025-07-02 06:41:16.384 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.384 blo = 49, bhi = 1101
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.384 g = []
2025-07-02 06:41:16.384 if alo < ahi:
2025-07-02 06:41:16.384 if blo < bhi:
2025-07-02 06:41:16.384 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.384 else:
2025-07-02 06:41:16.385 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.385 elif blo < bhi:
2025-07-02 06:41:16.385 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 > yield from g
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.385 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.385 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.385 alo = 49, ahi = 1101
2025-07-02 06:41:16.385 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.385 blo = 49, bhi = 1101
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.385 r"""
2025-07-02 06:41:16.385 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.385 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.385 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.386 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386 Example:
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386 >>> d = Differ()
2025-07-02 06:41:16.386 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.386 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.386 >>> print(''.join(results), end="")
2025-07-02 06:41:16.386 - abcDefghiJkl
2025-07-02 06:41:16.386 + abcdefGhijkl
2025-07-02 06:41:16.386 """
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.386 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.386 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.386 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.386 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386 # search for the pair that matches best without being identical
2025-07-02 06:41:16.387 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.387 # on junk -- unless we have to)
2025-07-02 06:41:16.387 for j in range(blo, bhi):
2025-07-02 06:41:16.387 bj = b[j]
2025-07-02 06:41:16.387 cruncher.set_seq2(bj)
2025-07-02 06:41:16.387 for i in range(alo, ahi):
2025-07-02 06:41:16.387 ai = a[i]
2025-07-02 06:41:16.387 if ai == bj:
2025-07-02 06:41:16.387 if eqi is None:
2025-07-02 06:41:16.387 eqi, eqj = i, j
2025-07-02 06:41:16.387 continue
2025-07-02 06:41:16.387 cruncher.set_seq1(ai)
2025-07-02 06:41:16.387 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.387 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.387 # compares by a factor of 3.
2025-07-02 06:41:16.387 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.387 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.387 # of the computation is cached by cruncher
2025-07-02 06:41:16.387 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.388 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.388 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.388 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.388 if best_ratio < cutoff:
2025-07-02 06:41:16.388 # no non-identical "pretty close" pair
2025-07-02 06:41:16.388 if eqi is None:
2025-07-02 06:41:16.388 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.388 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.388 return
2025-07-02 06:41:16.388 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.388 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.388 else:
2025-07-02 06:41:16.388 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.388 eqi = None
2025-07-02 06:41:16.388
2025-07-02 06:41:16.388 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.388 # identical
2025-07-02 06:41:16.388
2025-07-02 06:41:16.388 # pump out diffs from before the synch point
2025-07-02 06:41:16.389 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.389
2025-07-02 06:41:16.389 # do intraline marking on the synch pair
2025-07-02 06:41:16.389 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.389 if eqi is None:
2025-07-02 06:41:16.389 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.389 atags = btags = ""
2025-07-02 06:41:16.389 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.389 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.389 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.389 if tag == 'replace':
2025-07-02 06:41:16.389 atags += '^' * la
2025-07-02 06:41:16.389 btags += '^' * lb
2025-07-02 06:41:16.389 elif tag == 'delete':
2025-07-02 06:41:16.389 atags += '-' * la
2025-07-02 06:41:16.389 elif tag == 'insert':
2025-07-02 06:41:16.389 btags += '+' * lb
2025-07-02 06:41:16.389 elif tag == 'equal':
2025-07-02 06:41:16.389 atags += ' ' * la
2025-07-02 06:41:16.390 btags += ' ' * lb
2025-07-02 06:41:16.390 else:
2025-07-02 06:41:16.390 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.390 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.390 else:
2025-07-02 06:41:16.390 # the synch pair is identical
2025-07-02 06:41:16.390 yield ' ' + aelt
2025-07-02 06:41:16.390
2025-07-02 06:41:16.390 # pump out diffs from after the synch point
2025-07-02 06:41:16.390 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.390
2025-07-02 06:41:16.390 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.390 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.390
2025-07-02 06:41:16.390 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.390 alo = 50, ahi = 1101
2025-07-02 06:41:16.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.390 blo = 50, bhi = 1101
2025-07-02 06:41:16.390
2025-07-02 06:41:16.391 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.391 g = []
2025-07-02 06:41:16.391 if alo < ahi:
2025-07-02 06:41:16.391 if blo < bhi:
2025-07-02 06:41:16.391 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.391 else:
2025-07-02 06:41:16.391 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.391 elif blo < bhi:
2025-07-02 06:41:16.391 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.391
2025-07-02 06:41:16.391 > yield from g
2025-07-02 06:41:16.391
2025-07-02 06:41:16.391 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.391 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.391
2025-07-02 06:41:16.391 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.391 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.391 alo = 50, ahi = 1101
2025-07-02 06:41:16.391 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.392 blo = 50, bhi = 1101
2025-07-02 06:41:16.392
2025-07-02 06:41:16.392 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.392 r"""
2025-07-02 06:41:16.392 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.392 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.392 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.392 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.392
2025-07-02 06:41:16.392 Example:
2025-07-02 06:41:16.392
2025-07-02 06:41:16.392 >>> d = Differ()
2025-07-02 06:41:16.392 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.392 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.392 >>> print(''.join(results), end="")
2025-07-02 06:41:16.392 - abcDefghiJkl
2025-07-02 06:41:16.392 + abcdefGhijkl
2025-07-02 06:41:16.392 """
2025-07-02 06:41:16.393
2025-07-02 06:41:16.393 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.393 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.393 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.393 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.393 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.393
2025-07-02 06:41:16.393 # search for the pair that matches best without being identical
2025-07-02 06:41:16.393 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.393 # on junk -- unless we have to)
2025-07-02 06:41:16.393 for j in range(blo, bhi):
2025-07-02 06:41:16.393 bj = b[j]
2025-07-02 06:41:16.393 cruncher.set_seq2(bj)
2025-07-02 06:41:16.393 for i in range(alo, ahi):
2025-07-02 06:41:16.393 ai = a[i]
2025-07-02 06:41:16.393 if ai == bj:
2025-07-02 06:41:16.393 if eqi is None:
2025-07-02 06:41:16.393 eqi, eqj = i, j
2025-07-02 06:41:16.393 continue
2025-07-02 06:41:16.394 cruncher.set_seq1(ai)
2025-07-02 06:41:16.394 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.394 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.394 # compares by a factor of 3.
2025-07-02 06:41:16.394 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.394 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.394 # of the computation is cached by cruncher
2025-07-02 06:41:16.394 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.394 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.394 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.394 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.394 if best_ratio < cutoff:
2025-07-02 06:41:16.394 # no non-identical "pretty close" pair
2025-07-02 06:41:16.394 if eqi is None:
2025-07-02 06:41:16.394 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.394 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.394 return
2025-07-02 06:41:16.394 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.394 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.394 else:
2025-07-02 06:41:16.395 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.395 eqi = None
2025-07-02 06:41:16.395
2025-07-02 06:41:16.395 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.395 # identical
2025-07-02 06:41:16.395
2025-07-02 06:41:16.395 # pump out diffs from before the synch point
2025-07-02 06:41:16.395 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.395
2025-07-02 06:41:16.395 # do intraline marking on the synch pair
2025-07-02 06:41:16.395 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.395 if eqi is None:
2025-07-02 06:41:16.395 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.395 atags = btags = ""
2025-07-02 06:41:16.395 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.395 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.395 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.395 if tag == 'replace':
2025-07-02 06:41:16.395 atags += '^' * la
2025-07-02 06:41:16.395 btags += '^' * lb
2025-07-02 06:41:16.396 elif tag == 'delete':
2025-07-02 06:41:16.396 atags += '-' * la
2025-07-02 06:41:16.396 elif tag == 'insert':
2025-07-02 06:41:16.396 btags += '+' * lb
2025-07-02 06:41:16.396 elif tag == 'equal':
2025-07-02 06:41:16.396 atags += ' ' * la
2025-07-02 06:41:16.396 btags += ' ' * lb
2025-07-02 06:41:16.396 else:
2025-07-02 06:41:16.396 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.396 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.396 else:
2025-07-02 06:41:16.396 # the synch pair is identical
2025-07-02 06:41:16.396 yield ' ' + aelt
2025-07-02 06:41:16.396
2025-07-02 06:41:16.396 # pump out diffs from after the synch point
2025-07-02 06:41:16.396 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.396
2025-07-02 06:41:16.396 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.397
2025-07-02 06:41:16.397 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.397 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.397 alo = 51, ahi = 1101
2025-07-02 06:41:16.397 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.397 blo = 51, bhi = 1101
2025-07-02 06:41:16.397
2025-07-02 06:41:16.397 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.397 g = []
2025-07-02 06:41:16.397 if alo < ahi:
2025-07-02 06:41:16.397 if blo < bhi:
2025-07-02 06:41:16.397 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.397 else:
2025-07-02 06:41:16.397 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.397 elif blo < bhi:
2025-07-02 06:41:16.397 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.397
2025-07-02 06:41:16.397 > yield from g
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.398 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.398 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.398 alo = 51, ahi = 1101
2025-07-02 06:41:16.398 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.398 blo = 51, bhi = 1101
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.398 r"""
2025-07-02 06:41:16.398 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.398 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.398 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.398 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398 Example:
2025-07-02 06:41:16.398
2025-07-02 06:41:16.399 >>> d = Differ()
2025-07-02 06:41:16.399 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.399 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.399 >>> print(''.join(results), end="")
2025-07-02 06:41:16.399 - abcDefghiJkl
2025-07-02 06:41:16.399 + abcdefGhijkl
2025-07-02 06:41:16.399 """
2025-07-02 06:41:16.399
2025-07-02 06:41:16.399 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.399 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.399 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.399 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.399 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.399
2025-07-02 06:41:16.399 # search for the pair that matches best without being identical
2025-07-02 06:41:16.399 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.399 # on junk -- unless we have to)
2025-07-02 06:41:16.399 for j in range(blo, bhi):
2025-07-02 06:41:16.400 bj = b[j]
2025-07-02 06:41:16.400 cruncher.set_seq2(bj)
2025-07-02 06:41:16.400 for i in range(alo, ahi):
2025-07-02 06:41:16.400 ai = a[i]
2025-07-02 06:41:16.400 if ai == bj:
2025-07-02 06:41:16.400 if eqi is None:
2025-07-02 06:41:16.400 eqi, eqj = i, j
2025-07-02 06:41:16.400 continue
2025-07-02 06:41:16.400 cruncher.set_seq1(ai)
2025-07-02 06:41:16.400 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.400 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.400 # compares by a factor of 3.
2025-07-02 06:41:16.400 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.400 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.400 # of the computation is cached by cruncher
2025-07-02 06:41:16.400 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.400 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.400 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.400 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.401 if best_ratio < cutoff:
2025-07-02 06:41:16.401 # no non-identical "pretty close" pair
2025-07-02 06:41:16.401 if eqi is None:
2025-07-02 06:41:16.401 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.401 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.401 return
2025-07-02 06:41:16.401 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.401 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.401 else:
2025-07-02 06:41:16.401 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.401 eqi = None
2025-07-02 06:41:16.401
2025-07-02 06:41:16.401 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.401 # identical
2025-07-02 06:41:16.401
2025-07-02 06:41:16.401 # pump out diffs from before the synch point
2025-07-02 06:41:16.401 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.401
2025-07-02 06:41:16.401 # do intraline marking on the synch pair
2025-07-02 06:41:16.401 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.402 if eqi is None:
2025-07-02 06:41:16.402 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.402 atags = btags = ""
2025-07-02 06:41:16.402 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.402 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.402 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.402 if tag == 'replace':
2025-07-02 06:41:16.402 atags += '^' * la
2025-07-02 06:41:16.402 btags += '^' * lb
2025-07-02 06:41:16.402 elif tag == 'delete':
2025-07-02 06:41:16.402 atags += '-' * la
2025-07-02 06:41:16.402 elif tag == 'insert':
2025-07-02 06:41:16.402 btags += '+' * lb
2025-07-02 06:41:16.402 elif tag == 'equal':
2025-07-02 06:41:16.402 atags += ' ' * la
2025-07-02 06:41:16.402 btags += ' ' * lb
2025-07-02 06:41:16.402 else:
2025-07-02 06:41:16.402 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.402 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.403 else:
2025-07-02 06:41:16.403 # the synch pair is identical
2025-07-02 06:41:16.403 yield ' ' + aelt
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403 # pump out diffs from after the synch point
2025-07-02 06:41:16.403 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.403 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.403 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.403 alo = 52, ahi = 1101
2025-07-02 06:41:16.403 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.403 blo = 52, bhi = 1101
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.403 g = []
2025-07-02 06:41:16.403 if alo < ahi:
2025-07-02 06:41:16.403 if blo < bhi:
2025-07-02 06:41:16.404 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.404 else:
2025-07-02 06:41:16.404 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.404 elif blo < bhi:
2025-07-02 06:41:16.404 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 > yield from g
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.404 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.404 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.404 alo = 52, ahi = 1101
2025-07-02 06:41:16.404 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.404 blo = 52, bhi = 1101
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.404 r"""
2025-07-02 06:41:16.405 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.405 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.405 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.405 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.405
2025-07-02 06:41:16.405 Example:
2025-07-02 06:41:16.405
2025-07-02 06:41:16.405 >>> d = Differ()
2025-07-02 06:41:16.405 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.405 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.405 >>> print(''.join(results), end="")
2025-07-02 06:41:16.405 - abcDefghiJkl
2025-07-02 06:41:16.405 + abcdefGhijkl
2025-07-02 06:41:16.405 """
2025-07-02 06:41:16.405
2025-07-02 06:41:16.405 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.405 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.406 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.406 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.406 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.406
2025-07-02 06:41:16.406 # search for the pair that matches best without being identical
2025-07-02 06:41:16.406 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.406 # on junk -- unless we have to)
2025-07-02 06:41:16.406 for j in range(blo, bhi):
2025-07-02 06:41:16.406 bj = b[j]
2025-07-02 06:41:16.406 cruncher.set_seq2(bj)
2025-07-02 06:41:16.406 for i in range(alo, ahi):
2025-07-02 06:41:16.406 ai = a[i]
2025-07-02 06:41:16.406 if ai == bj:
2025-07-02 06:41:16.406 if eqi is None:
2025-07-02 06:41:16.406 eqi, eqj = i, j
2025-07-02 06:41:16.406 continue
2025-07-02 06:41:16.406 cruncher.set_seq1(ai)
2025-07-02 06:41:16.406 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.406 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.407 # compares by a factor of 3.
2025-07-02 06:41:16.407 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.407 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.407 # of the computation is cached by cruncher
2025-07-02 06:41:16.407 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.407 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.407 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.407 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.407 if best_ratio < cutoff:
2025-07-02 06:41:16.407 # no non-identical "pretty close" pair
2025-07-02 06:41:16.407 if eqi is None:
2025-07-02 06:41:16.407 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.407 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.407 return
2025-07-02 06:41:16.407 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.407 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.407 else:
2025-07-02 06:41:16.407 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.407 eqi = None
2025-07-02 06:41:16.408
2025-07-02 06:41:16.408 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.408 # identical
2025-07-02 06:41:16.408
2025-07-02 06:41:16.408 # pump out diffs from before the synch point
2025-07-02 06:41:16.408 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.408
2025-07-02 06:41:16.408 # do intraline marking on the synch pair
2025-07-02 06:41:16.408 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.408 if eqi is None:
2025-07-02 06:41:16.408 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.408 atags = btags = ""
2025-07-02 06:41:16.408 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.408 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.408 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.408 if tag == 'replace':
2025-07-02 06:41:16.408 atags += '^' * la
2025-07-02 06:41:16.408 btags += '^' * lb
2025-07-02 06:41:16.408 elif tag == 'delete':
2025-07-02 06:41:16.408 atags += '-' * la
2025-07-02 06:41:16.409 elif tag == 'insert':
2025-07-02 06:41:16.409 btags += '+' * lb
2025-07-02 06:41:16.409 elif tag == 'equal':
2025-07-02 06:41:16.409 atags += ' ' * la
2025-07-02 06:41:16.409 btags += ' ' * lb
2025-07-02 06:41:16.409 else:
2025-07-02 06:41:16.409 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.409 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.409 else:
2025-07-02 06:41:16.409 # the synch pair is identical
2025-07-02 06:41:16.409 yield ' ' + aelt
2025-07-02 06:41:16.409
2025-07-02 06:41:16.409 # pump out diffs from after the synch point
2025-07-02 06:41:16.409 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.409
2025-07-02 06:41:16.409 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.409 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.409
2025-07-02 06:41:16.409 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.409 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.410 alo = 53, ahi = 1101
2025-07-02 06:41:16.410 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.410 blo = 53, bhi = 1101
2025-07-02 06:41:16.410
2025-07-02 06:41:16.410 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.410 g = []
2025-07-02 06:41:16.410 if alo < ahi:
2025-07-02 06:41:16.410 if blo < bhi:
2025-07-02 06:41:16.410 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.410 else:
2025-07-02 06:41:16.410 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.410 elif blo < bhi:
2025-07-02 06:41:16.410 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.410
2025-07-02 06:41:16.410 > yield from g
2025-07-02 06:41:16.410
2025-07-02 06:41:16.410 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.410 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.410
2025-07-02 06:41:16.411 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.411 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.411 alo = 53, ahi = 1101
2025-07-02 06:41:16.411 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.411 blo = 53, bhi = 1101
2025-07-02 06:41:16.411
2025-07-02 06:41:16.411 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.411 r"""
2025-07-02 06:41:16.411 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.411 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.411 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.411 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.411
2025-07-02 06:41:16.411 Example:
2025-07-02 06:41:16.411
2025-07-02 06:41:16.411 >>> d = Differ()
2025-07-02 06:41:16.411 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.411 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.411 >>> print(''.join(results), end="")
2025-07-02 06:41:16.412 - abcDefghiJkl
2025-07-02 06:41:16.412 + abcdefGhijkl
2025-07-02 06:41:16.412 """
2025-07-02 06:41:16.412
2025-07-02 06:41:16.412 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.412 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.412 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.412 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.412 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.412
2025-07-02 06:41:16.412 # search for the pair that matches best without being identical
2025-07-02 06:41:16.412 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.412 # on junk -- unless we have to)
2025-07-02 06:41:16.412 for j in range(blo, bhi):
2025-07-02 06:41:16.412 bj = b[j]
2025-07-02 06:41:16.412 cruncher.set_seq2(bj)
2025-07-02 06:41:16.412 for i in range(alo, ahi):
2025-07-02 06:41:16.413 ai = a[i]
2025-07-02 06:41:16.413 if ai == bj:
2025-07-02 06:41:16.413 if eqi is None:
2025-07-02 06:41:16.413 eqi, eqj = i, j
2025-07-02 06:41:16.413 continue
2025-07-02 06:41:16.413 cruncher.set_seq1(ai)
2025-07-02 06:41:16.413 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.413 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.413 # compares by a factor of 3.
2025-07-02 06:41:16.413 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.413 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.413 # of the computation is cached by cruncher
2025-07-02 06:41:16.413 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.413 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.413 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.413 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.413 if best_ratio < cutoff:
2025-07-02 06:41:16.413 # no non-identical "pretty close" pair
2025-07-02 06:41:16.413 if eqi is None:
2025-07-02 06:41:16.414 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.414 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.414 return
2025-07-02 06:41:16.414 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.414 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.414 else:
2025-07-02 06:41:16.414 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.414 eqi = None
2025-07-02 06:41:16.414
2025-07-02 06:41:16.414 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.414 # identical
2025-07-02 06:41:16.414
2025-07-02 06:41:16.414 # pump out diffs from before the synch point
2025-07-02 06:41:16.414 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.414
2025-07-02 06:41:16.414 # do intraline marking on the synch pair
2025-07-02 06:41:16.414 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.414 if eqi is None:
2025-07-02 06:41:16.414 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.415 atags = btags = ""
2025-07-02 06:41:16.415 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.415 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.415 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.415 if tag == 'replace':
2025-07-02 06:41:16.415 atags += '^' * la
2025-07-02 06:41:16.415 btags += '^' * lb
2025-07-02 06:41:16.415 elif tag == 'delete':
2025-07-02 06:41:16.415 atags += '-' * la
2025-07-02 06:41:16.415 elif tag == 'insert':
2025-07-02 06:41:16.415 btags += '+' * lb
2025-07-02 06:41:16.415 elif tag == 'equal':
2025-07-02 06:41:16.415 atags += ' ' * la
2025-07-02 06:41:16.415 btags += ' ' * lb
2025-07-02 06:41:16.415 else:
2025-07-02 06:41:16.415 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.415 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.415 else:
2025-07-02 06:41:16.415 # the synch pair is identical
2025-07-02 06:41:16.415 yield ' ' + aelt
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416 # pump out diffs from after the synch point
2025-07-02 06:41:16.416 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.416 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.416 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.416 alo = 54, ahi = 1101
2025-07-02 06:41:16.416 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.416 blo = 54, bhi = 1101
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.416 g = []
2025-07-02 06:41:16.416 if alo < ahi:
2025-07-02 06:41:16.416 if blo < bhi:
2025-07-02 06:41:16.416 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.416 else:
2025-07-02 06:41:16.417 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.417 elif blo < bhi:
2025-07-02 06:41:16.417 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 > yield from g
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.417 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.417 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.417 alo = 54, ahi = 1101
2025-07-02 06:41:16.417 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.417 blo = 54, bhi = 1101
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.417 r"""
2025-07-02 06:41:16.417 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.417 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.417 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.418 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.418
2025-07-02 06:41:16.418 Example:
2025-07-02 06:41:16.418
2025-07-02 06:41:16.418 >>> d = Differ()
2025-07-02 06:41:16.418 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.418 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.418 >>> print(''.join(results), end="")
2025-07-02 06:41:16.418 - abcDefghiJkl
2025-07-02 06:41:16.418 + abcdefGhijkl
2025-07-02 06:41:16.418 """
2025-07-02 06:41:16.418
2025-07-02 06:41:16.418 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.418 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.418 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.418 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.418 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.419
2025-07-02 06:41:16.419 # search for the pair that matches best without being identical
2025-07-02 06:41:16.419 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.419 # on junk -- unless we have to)
2025-07-02 06:41:16.419 for j in range(blo, bhi):
2025-07-02 06:41:16.419 bj = b[j]
2025-07-02 06:41:16.419 cruncher.set_seq2(bj)
2025-07-02 06:41:16.419 for i in range(alo, ahi):
2025-07-02 06:41:16.419 ai = a[i]
2025-07-02 06:41:16.419 if ai == bj:
2025-07-02 06:41:16.419 if eqi is None:
2025-07-02 06:41:16.419 eqi, eqj = i, j
2025-07-02 06:41:16.419 continue
2025-07-02 06:41:16.419 cruncher.set_seq1(ai)
2025-07-02 06:41:16.419 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.419 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.419 # compares by a factor of 3.
2025-07-02 06:41:16.419 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.419 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.419 # of the computation is cached by cruncher
2025-07-02 06:41:16.420 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.420 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.420 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.420 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.420 if best_ratio < cutoff:
2025-07-02 06:41:16.420 # no non-identical "pretty close" pair
2025-07-02 06:41:16.420 if eqi is None:
2025-07-02 06:41:16.420 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.420 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.420 return
2025-07-02 06:41:16.420 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.420 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.420 else:
2025-07-02 06:41:16.420 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.420 eqi = None
2025-07-02 06:41:16.420
2025-07-02 06:41:16.420 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.420 # identical
2025-07-02 06:41:16.420
2025-07-02 06:41:16.420 # pump out diffs from before the synch point
2025-07-02 06:41:16.421 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.421
2025-07-02 06:41:16.421 # do intraline marking on the synch pair
2025-07-02 06:41:16.421 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.421 if eqi is None:
2025-07-02 06:41:16.421 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.421 atags = btags = ""
2025-07-02 06:41:16.421 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.421 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.421 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.421 if tag == 'replace':
2025-07-02 06:41:16.421 atags += '^' * la
2025-07-02 06:41:16.421 btags += '^' * lb
2025-07-02 06:41:16.421 elif tag == 'delete':
2025-07-02 06:41:16.421 atags += '-' * la
2025-07-02 06:41:16.421 elif tag == 'insert':
2025-07-02 06:41:16.421 btags += '+' * lb
2025-07-02 06:41:16.421 elif tag == 'equal':
2025-07-02 06:41:16.421 atags += ' ' * la
2025-07-02 06:41:16.422 btags += ' ' * lb
2025-07-02 06:41:16.422 else:
2025-07-02 06:41:16.422 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.422 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.422 else:
2025-07-02 06:41:16.422 # the synch pair is identical
2025-07-02 06:41:16.422 yield ' ' + aelt
2025-07-02 06:41:16.422
2025-07-02 06:41:16.422 # pump out diffs from after the synch point
2025-07-02 06:41:16.422 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.422
2025-07-02 06:41:16.422 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.422 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.422
2025-07-02 06:41:16.422 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.422 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.422 alo = 55, ahi = 1101
2025-07-02 06:41:16.422 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.422 blo = 55, bhi = 1101
2025-07-02 06:41:16.422
2025-07-02 06:41:16.423 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.423 g = []
2025-07-02 06:41:16.423 if alo < ahi:
2025-07-02 06:41:16.423 if blo < bhi:
2025-07-02 06:41:16.423 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.423 else:
2025-07-02 06:41:16.423 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.423 elif blo < bhi:
2025-07-02 06:41:16.423 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.423
2025-07-02 06:41:16.423 > yield from g
2025-07-02 06:41:16.423
2025-07-02 06:41:16.423 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.423 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.423
2025-07-02 06:41:16.423 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.423 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.423 alo = 55, ahi = 1101
2025-07-02 06:41:16.424 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.424 blo = 55, bhi = 1101
2025-07-02 06:41:16.424
2025-07-02 06:41:16.424 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.424 r"""
2025-07-02 06:41:16.424 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.424 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.424 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.424 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.424
2025-07-02 06:41:16.424 Example:
2025-07-02 06:41:16.424
2025-07-02 06:41:16.424 >>> d = Differ()
2025-07-02 06:41:16.424 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.424 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.424 >>> print(''.join(results), end="")
2025-07-02 06:41:16.424 - abcDefghiJkl
2025-07-02 06:41:16.424 + abcdefGhijkl
2025-07-02 06:41:16.425 """
2025-07-02 06:41:16.425
2025-07-02 06:41:16.425 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.425 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.425 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.425 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.425 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.425
2025-07-02 06:41:16.425 # search for the pair that matches best without being identical
2025-07-02 06:41:16.425 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.425 # on junk -- unless we have to)
2025-07-02 06:41:16.425 for j in range(blo, bhi):
2025-07-02 06:41:16.425 bj = b[j]
2025-07-02 06:41:16.425 cruncher.set_seq2(bj)
2025-07-02 06:41:16.425 for i in range(alo, ahi):
2025-07-02 06:41:16.425 ai = a[i]
2025-07-02 06:41:16.425 if ai == bj:
2025-07-02 06:41:16.425 if eqi is None:
2025-07-02 06:41:16.425 eqi, eqj = i, j
2025-07-02 06:41:16.426 continue
2025-07-02 06:41:16.426 cruncher.set_seq1(ai)
2025-07-02 06:41:16.426 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.426 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.426 # compares by a factor of 3.
2025-07-02 06:41:16.426 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.426 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.426 # of the computation is cached by cruncher
2025-07-02 06:41:16.426 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.426 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.426 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.426 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.426 if best_ratio < cutoff:
2025-07-02 06:41:16.426 # no non-identical "pretty close" pair
2025-07-02 06:41:16.426 if eqi is None:
2025-07-02 06:41:16.426 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.426 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.426 return
2025-07-02 06:41:16.426 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.426 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.427 else:
2025-07-02 06:41:16.427 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.427 eqi = None
2025-07-02 06:41:16.427
2025-07-02 06:41:16.427 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.427 # identical
2025-07-02 06:41:16.427
2025-07-02 06:41:16.427 # pump out diffs from before the synch point
2025-07-02 06:41:16.427 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.427
2025-07-02 06:41:16.427 # do intraline marking on the synch pair
2025-07-02 06:41:16.427 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.427 if eqi is None:
2025-07-02 06:41:16.427 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.427 atags = btags = ""
2025-07-02 06:41:16.427 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.427 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.427 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.427 if tag == 'replace':
2025-07-02 06:41:16.427 atags += '^' * la
2025-07-02 06:41:16.428 btags += '^' * lb
2025-07-02 06:41:16.428 elif tag == 'delete':
2025-07-02 06:41:16.428 atags += '-' * la
2025-07-02 06:41:16.428 elif tag == 'insert':
2025-07-02 06:41:16.428 btags += '+' * lb
2025-07-02 06:41:16.428 elif tag == 'equal':
2025-07-02 06:41:16.428 atags += ' ' * la
2025-07-02 06:41:16.428 btags += ' ' * lb
2025-07-02 06:41:16.428 else:
2025-07-02 06:41:16.428 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.428 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.428 else:
2025-07-02 06:41:16.428 # the synch pair is identical
2025-07-02 06:41:16.428 yield ' ' + aelt
2025-07-02 06:41:16.428
2025-07-02 06:41:16.428 # pump out diffs from after the synch point
2025-07-02 06:41:16.428 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.428
2025-07-02 06:41:16.429 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.429 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.429
2025-07-02 06:41:16.429 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.429 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.429 alo = 56, ahi = 1101
2025-07-02 06:41:16.429 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.429 blo = 56, bhi = 1101
2025-07-02 06:41:16.429
2025-07-02 06:41:16.429 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.429 g = []
2025-07-02 06:41:16.429 if alo < ahi:
2025-07-02 06:41:16.429 if blo < bhi:
2025-07-02 06:41:16.429 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.429 else:
2025-07-02 06:41:16.429 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.429 elif blo < bhi:
2025-07-02 06:41:16.429 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.429
2025-07-02 06:41:16.430 > yield from g
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.430 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.430 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.430 alo = 56, ahi = 1101
2025-07-02 06:41:16.430 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.430 blo = 56, bhi = 1101
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.430 r"""
2025-07-02 06:41:16.430 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.430 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.430 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.430 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430 Example:
2025-07-02 06:41:16.431
2025-07-02 06:41:16.431 >>> d = Differ()
2025-07-02 06:41:16.431 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.431 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.431 >>> print(''.join(results), end="")
2025-07-02 06:41:16.431 - abcDefghiJkl
2025-07-02 06:41:16.431 + abcdefGhijkl
2025-07-02 06:41:16.431 """
2025-07-02 06:41:16.431
2025-07-02 06:41:16.431 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.431 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.431 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.431 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.431 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.431
2025-07-02 06:41:16.431 # search for the pair that matches best without being identical
2025-07-02 06:41:16.431 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.432 # on junk -- unless we have to)
2025-07-02 06:41:16.432 for j in range(blo, bhi):
2025-07-02 06:41:16.432 bj = b[j]
2025-07-02 06:41:16.432 cruncher.set_seq2(bj)
2025-07-02 06:41:16.432 for i in range(alo, ahi):
2025-07-02 06:41:16.432 ai = a[i]
2025-07-02 06:41:16.432 if ai == bj:
2025-07-02 06:41:16.432 if eqi is None:
2025-07-02 06:41:16.432 eqi, eqj = i, j
2025-07-02 06:41:16.432 continue
2025-07-02 06:41:16.432 cruncher.set_seq1(ai)
2025-07-02 06:41:16.432 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.432 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.432 # compares by a factor of 3.
2025-07-02 06:41:16.432 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.432 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.432 # of the computation is cached by cruncher
2025-07-02 06:41:16.432 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.433 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.433 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.433 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.433 if best_ratio < cutoff:
2025-07-02 06:41:16.433 # no non-identical "pretty close" pair
2025-07-02 06:41:16.433 if eqi is None:
2025-07-02 06:41:16.433 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.433 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.433 return
2025-07-02 06:41:16.433 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.433 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.433 else:
2025-07-02 06:41:16.433 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.433 eqi = None
2025-07-02 06:41:16.433
2025-07-02 06:41:16.433 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.433 # identical
2025-07-02 06:41:16.433
2025-07-02 06:41:16.433 # pump out diffs from before the synch point
2025-07-02 06:41:16.434 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.434
2025-07-02 06:41:16.434 # do intraline marking on the synch pair
2025-07-02 06:41:16.434 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.434 if eqi is None:
2025-07-02 06:41:16.434 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.434 atags = btags = ""
2025-07-02 06:41:16.434 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.434 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.434 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.434 if tag == 'replace':
2025-07-02 06:41:16.434 atags += '^' * la
2025-07-02 06:41:16.434 btags += '^' * lb
2025-07-02 06:41:16.434 elif tag == 'delete':
2025-07-02 06:41:16.434 atags += '-' * la
2025-07-02 06:41:16.434 elif tag == 'insert':
2025-07-02 06:41:16.434 btags += '+' * lb
2025-07-02 06:41:16.434 elif tag == 'equal':
2025-07-02 06:41:16.434 atags += ' ' * la
2025-07-02 06:41:16.435 btags += ' ' * lb
2025-07-02 06:41:16.435 else:
2025-07-02 06:41:16.435 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.435 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.435 else:
2025-07-02 06:41:16.435 # the synch pair is identical
2025-07-02 06:41:16.435 yield ' ' + aelt
2025-07-02 06:41:16.435
2025-07-02 06:41:16.435 # pump out diffs from after the synch point
2025-07-02 06:41:16.435 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.435
2025-07-02 06:41:16.435 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.435 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.435
2025-07-02 06:41:16.435 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.435 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.435 alo = 57, ahi = 1101
2025-07-02 06:41:16.436 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.436 blo = 57, bhi = 1101
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.436 g = []
2025-07-02 06:41:16.436 if alo < ahi:
2025-07-02 06:41:16.436 if blo < bhi:
2025-07-02 06:41:16.436 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.436 else:
2025-07-02 06:41:16.436 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.436 elif blo < bhi:
2025-07-02 06:41:16.436 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 > yield from g
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.436 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.437 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.437 alo = 57, ahi = 1101
2025-07-02 06:41:16.437 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.437 blo = 57, bhi = 1101
2025-07-02 06:41:16.437
2025-07-02 06:41:16.437 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.437 r"""
2025-07-02 06:41:16.437 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.437 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.437 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.437 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.437
2025-07-02 06:41:16.437 Example:
2025-07-02 06:41:16.437
2025-07-02 06:41:16.437 >>> d = Differ()
2025-07-02 06:41:16.437 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.437 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.437 >>> print(''.join(results), end="")
2025-07-02 06:41:16.437 - abcDefghiJkl
2025-07-02 06:41:16.438 + abcdefGhijkl
2025-07-02 06:41:16.438 """
2025-07-02 06:41:16.438
2025-07-02 06:41:16.438 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.438 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.438 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.438 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.438 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.438
2025-07-02 06:41:16.438 # search for the pair that matches best without being identical
2025-07-02 06:41:16.438 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.438 # on junk -- unless we have to)
2025-07-02 06:41:16.438 for j in range(blo, bhi):
2025-07-02 06:41:16.438 bj = b[j]
2025-07-02 06:41:16.438 cruncher.set_seq2(bj)
2025-07-02 06:41:16.438 for i in range(alo, ahi):
2025-07-02 06:41:16.438 ai = a[i]
2025-07-02 06:41:16.439 if ai == bj:
2025-07-02 06:41:16.439 if eqi is None:
2025-07-02 06:41:16.439 eqi, eqj = i, j
2025-07-02 06:41:16.439 continue
2025-07-02 06:41:16.439 cruncher.set_seq1(ai)
2025-07-02 06:41:16.439 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.439 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.439 # compares by a factor of 3.
2025-07-02 06:41:16.439 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.439 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.439 # of the computation is cached by cruncher
2025-07-02 06:41:16.439 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.439 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.439 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.439 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.439 if best_ratio < cutoff:
2025-07-02 06:41:16.439 # no non-identical "pretty close" pair
2025-07-02 06:41:16.439 if eqi is None:
2025-07-02 06:41:16.439 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.440 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.440 return
2025-07-02 06:41:16.440 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.440 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.440 else:
2025-07-02 06:41:16.440 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.440 eqi = None
2025-07-02 06:41:16.440
2025-07-02 06:41:16.440 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.440 # identical
2025-07-02 06:41:16.440
2025-07-02 06:41:16.440 # pump out diffs from before the synch point
2025-07-02 06:41:16.440 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.440
2025-07-02 06:41:16.440 # do intraline marking on the synch pair
2025-07-02 06:41:16.440 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.440 if eqi is None:
2025-07-02 06:41:16.440 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.440 atags = btags = ""
2025-07-02 06:41:16.440 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.441 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.441 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.441 if tag == 'replace':
2025-07-02 06:41:16.441 atags += '^' * la
2025-07-02 06:41:16.441 btags += '^' * lb
2025-07-02 06:41:16.441 elif tag == 'delete':
2025-07-02 06:41:16.441 atags += '-' * la
2025-07-02 06:41:16.441 elif tag == 'insert':
2025-07-02 06:41:16.441 btags += '+' * lb
2025-07-02 06:41:16.441 elif tag == 'equal':
2025-07-02 06:41:16.441 atags += ' ' * la
2025-07-02 06:41:16.441 btags += ' ' * lb
2025-07-02 06:41:16.441 else:
2025-07-02 06:41:16.441 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.441 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.441 else:
2025-07-02 06:41:16.441 # the synch pair is identical
2025-07-02 06:41:16.441 yield ' ' + aelt
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442 # pump out diffs from after the synch point
2025-07-02 06:41:16.442 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.442 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.442 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.442 alo = 58, ahi = 1101
2025-07-02 06:41:16.442 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.442 blo = 58, bhi = 1101
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.442 g = []
2025-07-02 06:41:16.442 if alo < ahi:
2025-07-02 06:41:16.442 if blo < bhi:
2025-07-02 06:41:16.442 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.442 else:
2025-07-02 06:41:16.443 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.443 elif blo < bhi:
2025-07-02 06:41:16.443 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 > yield from g
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.443 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.443 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.443 alo = 58, ahi = 1101
2025-07-02 06:41:16.443 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.443 blo = 58, bhi = 1101
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.443 r"""
2025-07-02 06:41:16.443 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.443 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.444 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.444 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.444
2025-07-02 06:41:16.444 Example:
2025-07-02 06:41:16.444
2025-07-02 06:41:16.444 >>> d = Differ()
2025-07-02 06:41:16.444 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.444 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.444 >>> print(''.join(results), end="")
2025-07-02 06:41:16.444 - abcDefghiJkl
2025-07-02 06:41:16.444 + abcdefGhijkl
2025-07-02 06:41:16.444 """
2025-07-02 06:41:16.444
2025-07-02 06:41:16.444 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.444 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.444 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.444 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.444 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.445
2025-07-02 06:41:16.445 # search for the pair that matches best without being identical
2025-07-02 06:41:16.445 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.445 # on junk -- unless we have to)
2025-07-02 06:41:16.445 for j in range(blo, bhi):
2025-07-02 06:41:16.445 bj = b[j]
2025-07-02 06:41:16.445 cruncher.set_seq2(bj)
2025-07-02 06:41:16.445 for i in range(alo, ahi):
2025-07-02 06:41:16.445 ai = a[i]
2025-07-02 06:41:16.445 if ai == bj:
2025-07-02 06:41:16.445 if eqi is None:
2025-07-02 06:41:16.445 eqi, eqj = i, j
2025-07-02 06:41:16.445 continue
2025-07-02 06:41:16.445 cruncher.set_seq1(ai)
2025-07-02 06:41:16.445 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.445 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.445 # compares by a factor of 3.
2025-07-02 06:41:16.445 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.445 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.445 # of the computation is cached by cruncher
2025-07-02 06:41:16.446 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.446 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.446 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.446 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.446 if best_ratio < cutoff:
2025-07-02 06:41:16.446 # no non-identical "pretty close" pair
2025-07-02 06:41:16.446 if eqi is None:
2025-07-02 06:41:16.446 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.446 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.446 return
2025-07-02 06:41:16.446 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.446 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.446 else:
2025-07-02 06:41:16.446 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.446 eqi = None
2025-07-02 06:41:16.446
2025-07-02 06:41:16.446 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.446 # identical
2025-07-02 06:41:16.446
2025-07-02 06:41:16.446 # pump out diffs from before the synch point
2025-07-02 06:41:16.446 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.447
2025-07-02 06:41:16.447 # do intraline marking on the synch pair
2025-07-02 06:41:16.447 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.447 if eqi is None:
2025-07-02 06:41:16.447 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.447 atags = btags = ""
2025-07-02 06:41:16.447 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.447 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.447 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.447 if tag == 'replace':
2025-07-02 06:41:16.447 atags += '^' * la
2025-07-02 06:41:16.447 btags += '^' * lb
2025-07-02 06:41:16.447 elif tag == 'delete':
2025-07-02 06:41:16.447 atags += '-' * la
2025-07-02 06:41:16.447 elif tag == 'insert':
2025-07-02 06:41:16.447 btags += '+' * lb
2025-07-02 06:41:16.447 elif tag == 'equal':
2025-07-02 06:41:16.447 atags += ' ' * la
2025-07-02 06:41:16.447 btags += ' ' * lb
2025-07-02 06:41:16.447 else:
2025-07-02 06:41:16.448 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.448 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.448 else:
2025-07-02 06:41:16.448 # the synch pair is identical
2025-07-02 06:41:16.448 yield ' ' + aelt
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448 # pump out diffs from after the synch point
2025-07-02 06:41:16.448 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.448 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.448 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.448 alo = 59, ahi = 1101
2025-07-02 06:41:16.448 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.448 blo = 59, bhi = 1101
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.448 g = []
2025-07-02 06:41:16.449 if alo < ahi:
2025-07-02 06:41:16.449 if blo < bhi:
2025-07-02 06:41:16.449 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.449 else:
2025-07-02 06:41:16.449 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.449 elif blo < bhi:
2025-07-02 06:41:16.449 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 > yield from g
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.449 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.449 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.449 alo = 59, ahi = 1101
2025-07-02 06:41:16.449 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.449 blo = 59, bhi = 1101
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.449 r"""
2025-07-02 06:41:16.450 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.450 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.450 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.450 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.450
2025-07-02 06:41:16.450 Example:
2025-07-02 06:41:16.450
2025-07-02 06:41:16.450 >>> d = Differ()
2025-07-02 06:41:16.450 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.450 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.450 >>> print(''.join(results), end="")
2025-07-02 06:41:16.450 - abcDefghiJkl
2025-07-02 06:41:16.450 + abcdefGhijkl
2025-07-02 06:41:16.450 """
2025-07-02 06:41:16.450
2025-07-02 06:41:16.450 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.451 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.451 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.451 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.451 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.451
2025-07-02 06:41:16.451 # search for the pair that matches best without being identical
2025-07-02 06:41:16.451 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.451 # on junk -- unless we have to)
2025-07-02 06:41:16.451 for j in range(blo, bhi):
2025-07-02 06:41:16.451 bj = b[j]
2025-07-02 06:41:16.451 cruncher.set_seq2(bj)
2025-07-02 06:41:16.451 for i in range(alo, ahi):
2025-07-02 06:41:16.451 ai = a[i]
2025-07-02 06:41:16.451 if ai == bj:
2025-07-02 06:41:16.451 if eqi is None:
2025-07-02 06:41:16.451 eqi, eqj = i, j
2025-07-02 06:41:16.451 continue
2025-07-02 06:41:16.451 cruncher.set_seq1(ai)
2025-07-02 06:41:16.451 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.452 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.452 # compares by a factor of 3.
2025-07-02 06:41:16.452 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.452 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.452 # of the computation is cached by cruncher
2025-07-02 06:41:16.452 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.452 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.452 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.452 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.452 if best_ratio < cutoff:
2025-07-02 06:41:16.452 # no non-identical "pretty close" pair
2025-07-02 06:41:16.452 if eqi is None:
2025-07-02 06:41:16.452 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.452 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.452 return
2025-07-02 06:41:16.452 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.452 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.452 else:
2025-07-02 06:41:16.452 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.452 eqi = None
2025-07-02 06:41:16.453
2025-07-02 06:41:16.453 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.453 # identical
2025-07-02 06:41:16.453
2025-07-02 06:41:16.453 # pump out diffs from before the synch point
2025-07-02 06:41:16.453 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.453
2025-07-02 06:41:16.453 # do intraline marking on the synch pair
2025-07-02 06:41:16.453 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.453 if eqi is None:
2025-07-02 06:41:16.453 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.453 atags = btags = ""
2025-07-02 06:41:16.453 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.453 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.453 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.453 if tag == 'replace':
2025-07-02 06:41:16.453 atags += '^' * la
2025-07-02 06:41:16.453 btags += '^' * lb
2025-07-02 06:41:16.453 elif tag == 'delete':
2025-07-02 06:41:16.453 atags += '-' * la
2025-07-02 06:41:16.454 elif tag == 'insert':
2025-07-02 06:41:16.454 btags += '+' * lb
2025-07-02 06:41:16.454 elif tag == 'equal':
2025-07-02 06:41:16.454 atags += ' ' * la
2025-07-02 06:41:16.454 btags += ' ' * lb
2025-07-02 06:41:16.454 else:
2025-07-02 06:41:16.454 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.454 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.454 else:
2025-07-02 06:41:16.454 # the synch pair is identical
2025-07-02 06:41:16.454 yield ' ' + aelt
2025-07-02 06:41:16.454
2025-07-02 06:41:16.454 # pump out diffs from after the synch point
2025-07-02 06:41:16.454 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.454
2025-07-02 06:41:16.454 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.454 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.454
2025-07-02 06:41:16.454 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.455 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.455 alo = 60, ahi = 1101
2025-07-02 06:41:16.455 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.455 blo = 60, bhi = 1101
2025-07-02 06:41:16.455
2025-07-02 06:41:16.455 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.455 g = []
2025-07-02 06:41:16.455 if alo < ahi:
2025-07-02 06:41:16.455 if blo < bhi:
2025-07-02 06:41:16.455 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.455 else:
2025-07-02 06:41:16.455 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.455 elif blo < bhi:
2025-07-02 06:41:16.455 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.455
2025-07-02 06:41:16.455 > yield from g
2025-07-02 06:41:16.455
2025-07-02 06:41:16.455 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.455 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.455
2025-07-02 06:41:16.456 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.456 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.456 alo = 60, ahi = 1101
2025-07-02 06:41:16.456 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.456 blo = 60, bhi = 1101
2025-07-02 06:41:16.456
2025-07-02 06:41:16.456 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.456 r"""
2025-07-02 06:41:16.456 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.456 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.456 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.456 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.456
2025-07-02 06:41:16.456 Example:
2025-07-02 06:41:16.456
2025-07-02 06:41:16.456 >>> d = Differ()
2025-07-02 06:41:16.456 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.456 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.456 >>> print(''.join(results), end="")
2025-07-02 06:41:16.457 - abcDefghiJkl
2025-07-02 06:41:16.457 + abcdefGhijkl
2025-07-02 06:41:16.457 """
2025-07-02 06:41:16.457
2025-07-02 06:41:16.457 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.457 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.457 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.457 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.457 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.457
2025-07-02 06:41:16.457 # search for the pair that matches best without being identical
2025-07-02 06:41:16.457 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.457 # on junk -- unless we have to)
2025-07-02 06:41:16.457 for j in range(blo, bhi):
2025-07-02 06:41:16.457 bj = b[j]
2025-07-02 06:41:16.457 cruncher.set_seq2(bj)
2025-07-02 06:41:16.457 for i in range(alo, ahi):
2025-07-02 06:41:16.457 ai = a[i]
2025-07-02 06:41:16.458 if ai == bj:
2025-07-02 06:41:16.458 if eqi is None:
2025-07-02 06:41:16.458 eqi, eqj = i, j
2025-07-02 06:41:16.458 continue
2025-07-02 06:41:16.458 cruncher.set_seq1(ai)
2025-07-02 06:41:16.458 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.458 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.458 # compares by a factor of 3.
2025-07-02 06:41:16.458 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.458 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.458 # of the computation is cached by cruncher
2025-07-02 06:41:16.458 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.458 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.458 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.458 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.458 if best_ratio < cutoff:
2025-07-02 06:41:16.458 # no non-identical "pretty close" pair
2025-07-02 06:41:16.458 if eqi is None:
2025-07-02 06:41:16.459 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.459 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.459 return
2025-07-02 06:41:16.459 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.459 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.459 else:
2025-07-02 06:41:16.459 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.459 eqi = None
2025-07-02 06:41:16.459
2025-07-02 06:41:16.459 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.459 # identical
2025-07-02 06:41:16.459
2025-07-02 06:41:16.459 # pump out diffs from before the synch point
2025-07-02 06:41:16.459 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.459
2025-07-02 06:41:16.459 # do intraline marking on the synch pair
2025-07-02 06:41:16.459 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.459 if eqi is None:
2025-07-02 06:41:16.460 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.460 atags = btags = ""
2025-07-02 06:41:16.460 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.460 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.460 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.460 if tag == 'replace':
2025-07-02 06:41:16.460 atags += '^' * la
2025-07-02 06:41:16.460 btags += '^' * lb
2025-07-02 06:41:16.460 elif tag == 'delete':
2025-07-02 06:41:16.460 atags += '-' * la
2025-07-02 06:41:16.460 elif tag == 'insert':
2025-07-02 06:41:16.460 btags += '+' * lb
2025-07-02 06:41:16.460 elif tag == 'equal':
2025-07-02 06:41:16.460 atags += ' ' * la
2025-07-02 06:41:16.460 btags += ' ' * lb
2025-07-02 06:41:16.460 else:
2025-07-02 06:41:16.460 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.460 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.461 else:
2025-07-02 06:41:16.461 # the synch pair is identical
2025-07-02 06:41:16.461 yield ' ' + aelt
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461 # pump out diffs from after the synch point
2025-07-02 06:41:16.461 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.461 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.461 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.461 alo = 61, ahi = 1101
2025-07-02 06:41:16.461 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.461 blo = 61, bhi = 1101
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.461 g = []
2025-07-02 06:41:16.461 if alo < ahi:
2025-07-02 06:41:16.462 if blo < bhi:
2025-07-02 06:41:16.462 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.462 else:
2025-07-02 06:41:16.462 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.462 elif blo < bhi:
2025-07-02 06:41:16.462 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.462
2025-07-02 06:41:16.462 > yield from g
2025-07-02 06:41:16.462
2025-07-02 06:41:16.462 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.462 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.462
2025-07-02 06:41:16.462 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.462 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.462 alo = 61, ahi = 1101
2025-07-02 06:41:16.462 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.462 blo = 61, bhi = 1101
2025-07-02 06:41:16.462
2025-07-02 06:41:16.463 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.463 r"""
2025-07-02 06:41:16.463 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.463 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.463 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.463 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.463
2025-07-02 06:41:16.463 Example:
2025-07-02 06:41:16.463
2025-07-02 06:41:16.463 >>> d = Differ()
2025-07-02 06:41:16.463 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.463 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.463 >>> print(''.join(results), end="")
2025-07-02 06:41:16.463 - abcDefghiJkl
2025-07-02 06:41:16.463 + abcdefGhijkl
2025-07-02 06:41:16.463 """
2025-07-02 06:41:16.463
2025-07-02 06:41:16.463 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.464 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.464 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.464 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.464 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.464
2025-07-02 06:41:16.464 # search for the pair that matches best without being identical
2025-07-02 06:41:16.464 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.464 # on junk -- unless we have to)
2025-07-02 06:41:16.464 for j in range(blo, bhi):
2025-07-02 06:41:16.464 bj = b[j]
2025-07-02 06:41:16.464 cruncher.set_seq2(bj)
2025-07-02 06:41:16.464 for i in range(alo, ahi):
2025-07-02 06:41:16.464 ai = a[i]
2025-07-02 06:41:16.464 if ai == bj:
2025-07-02 06:41:16.464 if eqi is None:
2025-07-02 06:41:16.464 eqi, eqj = i, j
2025-07-02 06:41:16.464 continue
2025-07-02 06:41:16.464 cruncher.set_seq1(ai)
2025-07-02 06:41:16.464 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.464 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.465 # compares by a factor of 3.
2025-07-02 06:41:16.465 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.465 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.465 # of the computation is cached by cruncher
2025-07-02 06:41:16.465 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.465 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.465 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.465 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.465 if best_ratio < cutoff:
2025-07-02 06:41:16.465 # no non-identical "pretty close" pair
2025-07-02 06:41:16.465 if eqi is None:
2025-07-02 06:41:16.465 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.465 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.465 return
2025-07-02 06:41:16.465 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.465 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.465 else:
2025-07-02 06:41:16.465 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.465 eqi = None
2025-07-02 06:41:16.466
2025-07-02 06:41:16.466 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.466 # identical
2025-07-02 06:41:16.466
2025-07-02 06:41:16.466 # pump out diffs from before the synch point
2025-07-02 06:41:16.466 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.466
2025-07-02 06:41:16.466 # do intraline marking on the synch pair
2025-07-02 06:41:16.466 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.466 if eqi is None:
2025-07-02 06:41:16.466 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.466 atags = btags = ""
2025-07-02 06:41:16.466 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.466 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.466 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.466 if tag == 'replace':
2025-07-02 06:41:16.466 atags += '^' * la
2025-07-02 06:41:16.466 btags += '^' * lb
2025-07-02 06:41:16.466 elif tag == 'delete':
2025-07-02 06:41:16.466 atags += '-' * la
2025-07-02 06:41:16.467 elif tag == 'insert':
2025-07-02 06:41:16.467 btags += '+' * lb
2025-07-02 06:41:16.467 elif tag == 'equal':
2025-07-02 06:41:16.467 atags += ' ' * la
2025-07-02 06:41:16.467 btags += ' ' * lb
2025-07-02 06:41:16.467 else:
2025-07-02 06:41:16.467 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.467 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.467 else:
2025-07-02 06:41:16.467 # the synch pair is identical
2025-07-02 06:41:16.467 yield ' ' + aelt
2025-07-02 06:41:16.467
2025-07-02 06:41:16.467 # pump out diffs from after the synch point
2025-07-02 06:41:16.467 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.467
2025-07-02 06:41:16.467 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.467 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.467
2025-07-02 06:41:16.467 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.468 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.468 alo = 62, ahi = 1101
2025-07-02 06:41:16.468 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.468 blo = 62, bhi = 1101
2025-07-02 06:41:16.468
2025-07-02 06:41:16.468 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.468 g = []
2025-07-02 06:41:16.468 if alo < ahi:
2025-07-02 06:41:16.468 if blo < bhi:
2025-07-02 06:41:16.468 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.468 else:
2025-07-02 06:41:16.468 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.468 elif blo < bhi:
2025-07-02 06:41:16.468 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.468
2025-07-02 06:41:16.468 > yield from g
2025-07-02 06:41:16.468
2025-07-02 06:41:16.468 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.468 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.469 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.469 alo = 62, ahi = 1101
2025-07-02 06:41:16.469 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.469 blo = 62, bhi = 1101
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.469 r"""
2025-07-02 06:41:16.469 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.469 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.469 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.469 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469 Example:
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469 >>> d = Differ()
2025-07-02 06:41:16.469 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.469 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.469 >>> print(''.join(results), end="")
2025-07-02 06:41:16.470 - abcDefghiJkl
2025-07-02 06:41:16.470 + abcdefGhijkl
2025-07-02 06:41:16.470 """
2025-07-02 06:41:16.470
2025-07-02 06:41:16.470 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.470 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.470 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.470 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.470 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.470
2025-07-02 06:41:16.470 # search for the pair that matches best without being identical
2025-07-02 06:41:16.470 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.470 # on junk -- unless we have to)
2025-07-02 06:41:16.470 for j in range(blo, bhi):
2025-07-02 06:41:16.470 bj = b[j]
2025-07-02 06:41:16.470 cruncher.set_seq2(bj)
2025-07-02 06:41:16.470 for i in range(alo, ahi):
2025-07-02 06:41:16.471 ai = a[i]
2025-07-02 06:41:16.471 if ai == bj:
2025-07-02 06:41:16.471 if eqi is None:
2025-07-02 06:41:16.471 eqi, eqj = i, j
2025-07-02 06:41:16.471 continue
2025-07-02 06:41:16.471 cruncher.set_seq1(ai)
2025-07-02 06:41:16.471 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.471 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.471 # compares by a factor of 3.
2025-07-02 06:41:16.471 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.471 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.471 # of the computation is cached by cruncher
2025-07-02 06:41:16.471 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.471 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.471 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.471 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.471 if best_ratio < cutoff:
2025-07-02 06:41:16.471 # no non-identical "pretty close" pair
2025-07-02 06:41:16.471 if eqi is None:
2025-07-02 06:41:16.472 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.472 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.472 return
2025-07-02 06:41:16.472 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.472 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.472 else:
2025-07-02 06:41:16.472 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.472 eqi = None
2025-07-02 06:41:16.472
2025-07-02 06:41:16.472 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.472 # identical
2025-07-02 06:41:16.472
2025-07-02 06:41:16.472 # pump out diffs from before the synch point
2025-07-02 06:41:16.472 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.472
2025-07-02 06:41:16.472 # do intraline marking on the synch pair
2025-07-02 06:41:16.472 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.472 if eqi is None:
2025-07-02 06:41:16.472 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.472 atags = btags = ""
2025-07-02 06:41:16.473 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.473 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.473 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.473 if tag == 'replace':
2025-07-02 06:41:16.473 atags += '^' * la
2025-07-02 06:41:16.473 btags += '^' * lb
2025-07-02 06:41:16.473 elif tag == 'delete':
2025-07-02 06:41:16.473 atags += '-' * la
2025-07-02 06:41:16.473 elif tag == 'insert':
2025-07-02 06:41:16.473 btags += '+' * lb
2025-07-02 06:41:16.473 elif tag == 'equal':
2025-07-02 06:41:16.473 atags += ' ' * la
2025-07-02 06:41:16.473 btags += ' ' * lb
2025-07-02 06:41:16.473 else:
2025-07-02 06:41:16.473 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.473 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.473 else:
2025-07-02 06:41:16.473 # the synch pair is identical
2025-07-02 06:41:16.473 yield ' ' + aelt
2025-07-02 06:41:16.473
2025-07-02 06:41:16.474 # pump out diffs from after the synch point
2025-07-02 06:41:16.474 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.474
2025-07-02 06:41:16.474 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.474 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.474
2025-07-02 06:41:16.474 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.474 alo = 63, ahi = 1101
2025-07-02 06:41:16.474 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.474 blo = 63, bhi = 1101
2025-07-02 06:41:16.474
2025-07-02 06:41:16.474 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.474 g = []
2025-07-02 06:41:16.474 if alo < ahi:
2025-07-02 06:41:16.474 if blo < bhi:
2025-07-02 06:41:16.474 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.474 else:
2025-07-02 06:41:16.474 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.475 elif blo < bhi:
2025-07-02 06:41:16.475 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 > yield from g
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.475 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.475 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.475 alo = 63, ahi = 1101
2025-07-02 06:41:16.475 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.475 blo = 63, bhi = 1101
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.475 r"""
2025-07-02 06:41:16.475 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.475 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.475 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.476 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.476
2025-07-02 06:41:16.476 Example:
2025-07-02 06:41:16.476
2025-07-02 06:41:16.476 >>> d = Differ()
2025-07-02 06:41:16.476 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.476 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.476 >>> print(''.join(results), end="")
2025-07-02 06:41:16.476 - abcDefghiJkl
2025-07-02 06:41:16.476 + abcdefGhijkl
2025-07-02 06:41:16.476 """
2025-07-02 06:41:16.476
2025-07-02 06:41:16.476 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.476 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.476 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.476 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.476 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.477
2025-07-02 06:41:16.477 # search for the pair that matches best without being identical
2025-07-02 06:41:16.477 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.477 # on junk -- unless we have to)
2025-07-02 06:41:16.477 for j in range(blo, bhi):
2025-07-02 06:41:16.477 bj = b[j]
2025-07-02 06:41:16.477 cruncher.set_seq2(bj)
2025-07-02 06:41:16.477 for i in range(alo, ahi):
2025-07-02 06:41:16.477 ai = a[i]
2025-07-02 06:41:16.477 if ai == bj:
2025-07-02 06:41:16.477 if eqi is None:
2025-07-02 06:41:16.477 eqi, eqj = i, j
2025-07-02 06:41:16.477 continue
2025-07-02 06:41:16.477 cruncher.set_seq1(ai)
2025-07-02 06:41:16.478 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.478 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.478 # compares by a factor of 3.
2025-07-02 06:41:16.478 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.478 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.478 # of the computation is cached by cruncher
2025-07-02 06:41:16.478 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.478 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.478 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.478 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.478 if best_ratio < cutoff:
2025-07-02 06:41:16.478 # no non-identical "pretty close" pair
2025-07-02 06:41:16.478 if eqi is None:
2025-07-02 06:41:16.478 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.478 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.478 return
2025-07-02 06:41:16.478 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.478 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.478 else:
2025-07-02 06:41:16.479 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.479 eqi = None
2025-07-02 06:41:16.479
2025-07-02 06:41:16.479 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.479 # identical
2025-07-02 06:41:16.479
2025-07-02 06:41:16.479 # pump out diffs from before the synch point
2025-07-02 06:41:16.479 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.479
2025-07-02 06:41:16.479 # do intraline marking on the synch pair
2025-07-02 06:41:16.479 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.479 if eqi is None:
2025-07-02 06:41:16.479 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.479 atags = btags = ""
2025-07-02 06:41:16.479 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.479 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.479 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.479 if tag == 'replace':
2025-07-02 06:41:16.479 atags += '^' * la
2025-07-02 06:41:16.479 btags += '^' * lb
2025-07-02 06:41:16.480 elif tag == 'delete':
2025-07-02 06:41:16.480 atags += '-' * la
2025-07-02 06:41:16.480 elif tag == 'insert':
2025-07-02 06:41:16.480 btags += '+' * lb
2025-07-02 06:41:16.480 elif tag == 'equal':
2025-07-02 06:41:16.480 atags += ' ' * la
2025-07-02 06:41:16.480 btags += ' ' * lb
2025-07-02 06:41:16.480 else:
2025-07-02 06:41:16.480 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.480 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.480 else:
2025-07-02 06:41:16.480 # the synch pair is identical
2025-07-02 06:41:16.480 yield ' ' + aelt
2025-07-02 06:41:16.480
2025-07-02 06:41:16.480 # pump out diffs from after the synch point
2025-07-02 06:41:16.480 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.480
2025-07-02 06:41:16.480 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.480 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.480
2025-07-02 06:41:16.480 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.481 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.481 alo = 64, ahi = 1101
2025-07-02 06:41:16.481 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.481 blo = 64, bhi = 1101
2025-07-02 06:41:16.481
2025-07-02 06:41:16.481 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.481 g = []
2025-07-02 06:41:16.481 if alo < ahi:
2025-07-02 06:41:16.481 if blo < bhi:
2025-07-02 06:41:16.481 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.481 else:
2025-07-02 06:41:16.481 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.481 elif blo < bhi:
2025-07-02 06:41:16.481 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.481
2025-07-02 06:41:16.481 > yield from g
2025-07-02 06:41:16.481
2025-07-02 06:41:16.481 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.481 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.481
2025-07-02 06:41:16.482 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.482 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.482 alo = 64, ahi = 1101
2025-07-02 06:41:16.482 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.482 blo = 64, bhi = 1101
2025-07-02 06:41:16.482
2025-07-02 06:41:16.482 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.482 r"""
2025-07-02 06:41:16.482 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.482 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.482 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.482 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.482
2025-07-02 06:41:16.482 Example:
2025-07-02 06:41:16.482
2025-07-02 06:41:16.482 >>> d = Differ()
2025-07-02 06:41:16.482 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.482 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.482 >>> print(''.join(results), end="")
2025-07-02 06:41:16.482 - abcDefghiJkl
2025-07-02 06:41:16.483 + abcdefGhijkl
2025-07-02 06:41:16.483 """
2025-07-02 06:41:16.483
2025-07-02 06:41:16.483 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.483 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.483 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.483 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.483 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.483
2025-07-02 06:41:16.483 # search for the pair that matches best without being identical
2025-07-02 06:41:16.483 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.483 # on junk -- unless we have to)
2025-07-02 06:41:16.483 for j in range(blo, bhi):
2025-07-02 06:41:16.483 bj = b[j]
2025-07-02 06:41:16.483 cruncher.set_seq2(bj)
2025-07-02 06:41:16.483 for i in range(alo, ahi):
2025-07-02 06:41:16.483 ai = a[i]
2025-07-02 06:41:16.483 if ai == bj:
2025-07-02 06:41:16.483 if eqi is None:
2025-07-02 06:41:16.484 eqi, eqj = i, j
2025-07-02 06:41:16.484 continue
2025-07-02 06:41:16.484 cruncher.set_seq1(ai)
2025-07-02 06:41:16.484 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.484 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.484 # compares by a factor of 3.
2025-07-02 06:41:16.484 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.484 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.484 # of the computation is cached by cruncher
2025-07-02 06:41:16.484 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.484 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.484 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.484 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.484 if best_ratio < cutoff:
2025-07-02 06:41:16.484 # no non-identical "pretty close" pair
2025-07-02 06:41:16.484 if eqi is None:
2025-07-02 06:41:16.484 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.484 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.484 return
2025-07-02 06:41:16.484 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.485 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.485 else:
2025-07-02 06:41:16.485 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.485 eqi = None
2025-07-02 06:41:16.485
2025-07-02 06:41:16.485 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.485 # identical
2025-07-02 06:41:16.485
2025-07-02 06:41:16.485 # pump out diffs from before the synch point
2025-07-02 06:41:16.485 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.485
2025-07-02 06:41:16.485 # do intraline marking on the synch pair
2025-07-02 06:41:16.485 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.485 if eqi is None:
2025-07-02 06:41:16.485 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.485 atags = btags = ""
2025-07-02 06:41:16.485 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.485 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.486 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.486 if tag == 'replace':
2025-07-02 06:41:16.486 atags += '^' * la
2025-07-02 06:41:16.486 btags += '^' * lb
2025-07-02 06:41:16.486 elif tag == 'delete':
2025-07-02 06:41:16.486 atags += '-' * la
2025-07-02 06:41:16.486 elif tag == 'insert':
2025-07-02 06:41:16.486 btags += '+' * lb
2025-07-02 06:41:16.486 elif tag == 'equal':
2025-07-02 06:41:16.486 atags += ' ' * la
2025-07-02 06:41:16.486 btags += ' ' * lb
2025-07-02 06:41:16.486 else:
2025-07-02 06:41:16.486 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.486 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.486 else:
2025-07-02 06:41:16.486 # the synch pair is identical
2025-07-02 06:41:16.486 yield ' ' + aelt
2025-07-02 06:41:16.486
2025-07-02 06:41:16.486 # pump out diffs from after the synch point
2025-07-02 06:41:16.486 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.487
2025-07-02 06:41:16.487 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.487
2025-07-02 06:41:16.487 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.487 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.487 alo = 65, ahi = 1101
2025-07-02 06:41:16.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.487 blo = 65, bhi = 1101
2025-07-02 06:41:16.487
2025-07-02 06:41:16.487 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.487 g = []
2025-07-02 06:41:16.487 if alo < ahi:
2025-07-02 06:41:16.487 if blo < bhi:
2025-07-02 06:41:16.487 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.487 else:
2025-07-02 06:41:16.487 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.487 elif blo < bhi:
2025-07-02 06:41:16.487 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 > yield from g
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.488 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.488 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.488 alo = 65, ahi = 1101
2025-07-02 06:41:16.488 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.488 blo = 65, bhi = 1101
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.488 r"""
2025-07-02 06:41:16.488 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.488 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.488 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.488 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 Example:
2025-07-02 06:41:16.488
2025-07-02 06:41:16.489 >>> d = Differ()
2025-07-02 06:41:16.489 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.489 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.489 >>> print(''.join(results), end="")
2025-07-02 06:41:16.489 - abcDefghiJkl
2025-07-02 06:41:16.489 + abcdefGhijkl
2025-07-02 06:41:16.489 """
2025-07-02 06:41:16.489
2025-07-02 06:41:16.489 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.489 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.489 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.489 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.489 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.489
2025-07-02 06:41:16.489 # search for the pair that matches best without being identical
2025-07-02 06:41:16.489 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.489 # on junk -- unless we have to)
2025-07-02 06:41:16.489 for j in range(blo, bhi):
2025-07-02 06:41:16.490 bj = b[j]
2025-07-02 06:41:16.490 cruncher.set_seq2(bj)
2025-07-02 06:41:16.490 for i in range(alo, ahi):
2025-07-02 06:41:16.490 ai = a[i]
2025-07-02 06:41:16.490 if ai == bj:
2025-07-02 06:41:16.490 if eqi is None:
2025-07-02 06:41:16.490 eqi, eqj = i, j
2025-07-02 06:41:16.490 continue
2025-07-02 06:41:16.490 cruncher.set_seq1(ai)
2025-07-02 06:41:16.490 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.490 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.490 # compares by a factor of 3.
2025-07-02 06:41:16.490 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.490 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.490 # of the computation is cached by cruncher
2025-07-02 06:41:16.490 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.490 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.490 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.490 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.490 if best_ratio < cutoff:
2025-07-02 06:41:16.490 # no non-identical "pretty close" pair
2025-07-02 06:41:16.491 if eqi is None:
2025-07-02 06:41:16.491 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.491 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.491 return
2025-07-02 06:41:16.491 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.491 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.491 else:
2025-07-02 06:41:16.491 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.491 eqi = None
2025-07-02 06:41:16.491
2025-07-02 06:41:16.491 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.491 # identical
2025-07-02 06:41:16.491
2025-07-02 06:41:16.491 # pump out diffs from before the synch point
2025-07-02 06:41:16.491 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.491
2025-07-02 06:41:16.491 # do intraline marking on the synch pair
2025-07-02 06:41:16.491 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.492 if eqi is None:
2025-07-02 06:41:16.492 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.492 atags = btags = ""
2025-07-02 06:41:16.492 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.492 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.492 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.492 if tag == 'replace':
2025-07-02 06:41:16.492 atags += '^' * la
2025-07-02 06:41:16.492 btags += '^' * lb
2025-07-02 06:41:16.492 elif tag == 'delete':
2025-07-02 06:41:16.492 atags += '-' * la
2025-07-02 06:41:16.492 elif tag == 'insert':
2025-07-02 06:41:16.492 btags += '+' * lb
2025-07-02 06:41:16.492 elif tag == 'equal':
2025-07-02 06:41:16.492 atags += ' ' * la
2025-07-02 06:41:16.492 btags += ' ' * lb
2025-07-02 06:41:16.492 else:
2025-07-02 06:41:16.492 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.492 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.492 else:
2025-07-02 06:41:16.493 # the synch pair is identical
2025-07-02 06:41:16.493 yield ' ' + aelt
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493 # pump out diffs from after the synch point
2025-07-02 06:41:16.493 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.493 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.493 alo = 66, ahi = 1101
2025-07-02 06:41:16.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.493 blo = 66, bhi = 1101
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.493 g = []
2025-07-02 06:41:16.493 if alo < ahi:
2025-07-02 06:41:16.493 if blo < bhi:
2025-07-02 06:41:16.493 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.494 else:
2025-07-02 06:41:16.494 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.494 elif blo < bhi:
2025-07-02 06:41:16.494 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 > yield from g
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.494 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.494 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.494 alo = 66, ahi = 1101
2025-07-02 06:41:16.494 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.494 blo = 66, bhi = 1101
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.494 r"""
2025-07-02 06:41:16.495 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.495 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.495 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.495 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.495
2025-07-02 06:41:16.495 Example:
2025-07-02 06:41:16.495
2025-07-02 06:41:16.495 >>> d = Differ()
2025-07-02 06:41:16.495 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.495 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.495 >>> print(''.join(results), end="")
2025-07-02 06:41:16.495 - abcDefghiJkl
2025-07-02 06:41:16.495 + abcdefGhijkl
2025-07-02 06:41:16.495 """
2025-07-02 06:41:16.495
2025-07-02 06:41:16.495 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.495 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.495 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.496 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.496 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.496
2025-07-02 06:41:16.496 # search for the pair that matches best without being identical
2025-07-02 06:41:16.496 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.496 # on junk -- unless we have to)
2025-07-02 06:41:16.496 for j in range(blo, bhi):
2025-07-02 06:41:16.496 bj = b[j]
2025-07-02 06:41:16.496 cruncher.set_seq2(bj)
2025-07-02 06:41:16.496 for i in range(alo, ahi):
2025-07-02 06:41:16.496 ai = a[i]
2025-07-02 06:41:16.496 if ai == bj:
2025-07-02 06:41:16.496 if eqi is None:
2025-07-02 06:41:16.496 eqi, eqj = i, j
2025-07-02 06:41:16.496 continue
2025-07-02 06:41:16.496 cruncher.set_seq1(ai)
2025-07-02 06:41:16.496 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.496 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.496 # compares by a factor of 3.
2025-07-02 06:41:16.496 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.497 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.497 # of the computation is cached by cruncher
2025-07-02 06:41:16.497 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.497 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.497 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.497 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.497 if best_ratio < cutoff:
2025-07-02 06:41:16.497 # no non-identical "pretty close" pair
2025-07-02 06:41:16.497 if eqi is None:
2025-07-02 06:41:16.497 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.497 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.497 return
2025-07-02 06:41:16.497 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.497 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.497 else:
2025-07-02 06:41:16.497 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.497 eqi = None
2025-07-02 06:41:16.497
2025-07-02 06:41:16.497 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.497 # identical
2025-07-02 06:41:16.498
2025-07-02 06:41:16.498 # pump out diffs from before the synch point
2025-07-02 06:41:16.498 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.498
2025-07-02 06:41:16.498 # do intraline marking on the synch pair
2025-07-02 06:41:16.498 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.498 if eqi is None:
2025-07-02 06:41:16.498 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.498 atags = btags = ""
2025-07-02 06:41:16.498 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.498 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.498 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.498 if tag == 'replace':
2025-07-02 06:41:16.498 atags += '^' * la
2025-07-02 06:41:16.498 btags += '^' * lb
2025-07-02 06:41:16.498 elif tag == 'delete':
2025-07-02 06:41:16.498 atags += '-' * la
2025-07-02 06:41:16.498 elif tag == 'insert':
2025-07-02 06:41:16.498 btags += '+' * lb
2025-07-02 06:41:16.498 elif tag == 'equal':
2025-07-02 06:41:16.498 atags += ' ' * la
2025-07-02 06:41:16.499 btags += ' ' * lb
2025-07-02 06:41:16.499 else:
2025-07-02 06:41:16.499 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.499 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.499 else:
2025-07-02 06:41:16.499 # the synch pair is identical
2025-07-02 06:41:16.499 yield ' ' + aelt
2025-07-02 06:41:16.499
2025-07-02 06:41:16.499 # pump out diffs from after the synch point
2025-07-02 06:41:16.499 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.499
2025-07-02 06:41:16.499 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.499
2025-07-02 06:41:16.499 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.499 alo = 67, ahi = 1101
2025-07-02 06:41:16.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.499 blo = 67, bhi = 1101
2025-07-02 06:41:16.499
2025-07-02 06:41:16.500 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.500 g = []
2025-07-02 06:41:16.500 if alo < ahi:
2025-07-02 06:41:16.500 if blo < bhi:
2025-07-02 06:41:16.500 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.500 else:
2025-07-02 06:41:16.500 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.500 elif blo < bhi:
2025-07-02 06:41:16.500 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.500
2025-07-02 06:41:16.500 > yield from g
2025-07-02 06:41:16.500
2025-07-02 06:41:16.500 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.500 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.500
2025-07-02 06:41:16.500 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.500 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.500 alo = 67, ahi = 1101
2025-07-02 06:41:16.500 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.500 blo = 67, bhi = 1101
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.501 r"""
2025-07-02 06:41:16.501 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.501 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.501 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.501 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501 Example:
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501 >>> d = Differ()
2025-07-02 06:41:16.501 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.501 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.501 >>> print(''.join(results), end="")
2025-07-02 06:41:16.501 - abcDefghiJkl
2025-07-02 06:41:16.501 + abcdefGhijkl
2025-07-02 06:41:16.501 """
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.502 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.502 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.502 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.502 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.502
2025-07-02 06:41:16.502 # search for the pair that matches best without being identical
2025-07-02 06:41:16.502 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.502 # on junk -- unless we have to)
2025-07-02 06:41:16.502 for j in range(blo, bhi):
2025-07-02 06:41:16.502 bj = b[j]
2025-07-02 06:41:16.502 cruncher.set_seq2(bj)
2025-07-02 06:41:16.502 for i in range(alo, ahi):
2025-07-02 06:41:16.502 ai = a[i]
2025-07-02 06:41:16.502 if ai == bj:
2025-07-02 06:41:16.502 if eqi is None:
2025-07-02 06:41:16.502 eqi, eqj = i, j
2025-07-02 06:41:16.502 continue
2025-07-02 06:41:16.502 cruncher.set_seq1(ai)
2025-07-02 06:41:16.502 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.502 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.503 # compares by a factor of 3.
2025-07-02 06:41:16.503 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.503 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.503 # of the computation is cached by cruncher
2025-07-02 06:41:16.503 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.503 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.503 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.503 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.503 if best_ratio < cutoff:
2025-07-02 06:41:16.503 # no non-identical "pretty close" pair
2025-07-02 06:41:16.503 if eqi is None:
2025-07-02 06:41:16.503 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.503 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.503 return
2025-07-02 06:41:16.503 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.503 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.503 else:
2025-07-02 06:41:16.503 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.503 eqi = None
2025-07-02 06:41:16.504
2025-07-02 06:41:16.504 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.504 # identical
2025-07-02 06:41:16.504
2025-07-02 06:41:16.504 # pump out diffs from before the synch point
2025-07-02 06:41:16.504 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.504
2025-07-02 06:41:16.504 # do intraline marking on the synch pair
2025-07-02 06:41:16.504 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.504 if eqi is None:
2025-07-02 06:41:16.504 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.504 atags = btags = ""
2025-07-02 06:41:16.504 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.504 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.504 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.504 if tag == 'replace':
2025-07-02 06:41:16.504 atags += '^' * la
2025-07-02 06:41:16.504 btags += '^' * lb
2025-07-02 06:41:16.504 elif tag == 'delete':
2025-07-02 06:41:16.504 atags += '-' * la
2025-07-02 06:41:16.505 elif tag == 'insert':
2025-07-02 06:41:16.505 btags += '+' * lb
2025-07-02 06:41:16.505 elif tag == 'equal':
2025-07-02 06:41:16.505 atags += ' ' * la
2025-07-02 06:41:16.505 btags += ' ' * lb
2025-07-02 06:41:16.505 else:
2025-07-02 06:41:16.505 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.505 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.505 else:
2025-07-02 06:41:16.505 # the synch pair is identical
2025-07-02 06:41:16.505 yield ' ' + aelt
2025-07-02 06:41:16.505
2025-07-02 06:41:16.505 # pump out diffs from after the synch point
2025-07-02 06:41:16.505 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.505
2025-07-02 06:41:16.505 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.505
2025-07-02 06:41:16.505 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.505 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.506 alo = 70, ahi = 1101
2025-07-02 06:41:16.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.506 blo = 70, bhi = 1101
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.506 g = []
2025-07-02 06:41:16.506 if alo < ahi:
2025-07-02 06:41:16.506 if blo < bhi:
2025-07-02 06:41:16.506 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.506 else:
2025-07-02 06:41:16.506 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.506 elif blo < bhi:
2025-07-02 06:41:16.506 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 > yield from g
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.506 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.506 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.507 alo = 70, ahi = 1101
2025-07-02 06:41:16.507 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.507 blo = 70, bhi = 1101
2025-07-02 06:41:16.507
2025-07-02 06:41:16.507 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.507 r"""
2025-07-02 06:41:16.507 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.507 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.507 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.507 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.507
2025-07-02 06:41:16.507 Example:
2025-07-02 06:41:16.507
2025-07-02 06:41:16.507 >>> d = Differ()
2025-07-02 06:41:16.507 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.507 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.507 >>> print(''.join(results), end="")
2025-07-02 06:41:16.507 - abcDefghiJkl
2025-07-02 06:41:16.508 + abcdefGhijkl
2025-07-02 06:41:16.508 """
2025-07-02 06:41:16.508
2025-07-02 06:41:16.508 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.508 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.508 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.508 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.508 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.508
2025-07-02 06:41:16.508 # search for the pair that matches best without being identical
2025-07-02 06:41:16.508 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.508 # on junk -- unless we have to)
2025-07-02 06:41:16.508 for j in range(blo, bhi):
2025-07-02 06:41:16.508 bj = b[j]
2025-07-02 06:41:16.508 cruncher.set_seq2(bj)
2025-07-02 06:41:16.508 for i in range(alo, ahi):
2025-07-02 06:41:16.508 ai = a[i]
2025-07-02 06:41:16.508 if ai == bj:
2025-07-02 06:41:16.508 if eqi is None:
2025-07-02 06:41:16.509 eqi, eqj = i, j
2025-07-02 06:41:16.509 continue
2025-07-02 06:41:16.509 cruncher.set_seq1(ai)
2025-07-02 06:41:16.509 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.509 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.509 # compares by a factor of 3.
2025-07-02 06:41:16.509 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.509 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.509 # of the computation is cached by cruncher
2025-07-02 06:41:16.509 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.509 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.509 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.509 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.509 if best_ratio < cutoff:
2025-07-02 06:41:16.509 # no non-identical "pretty close" pair
2025-07-02 06:41:16.509 if eqi is None:
2025-07-02 06:41:16.509 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.509 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.509 return
2025-07-02 06:41:16.509 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.510 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.510 else:
2025-07-02 06:41:16.510 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.510 eqi = None
2025-07-02 06:41:16.510
2025-07-02 06:41:16.510 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.510 # identical
2025-07-02 06:41:16.510
2025-07-02 06:41:16.510 # pump out diffs from before the synch point
2025-07-02 06:41:16.510 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.510
2025-07-02 06:41:16.510 # do intraline marking on the synch pair
2025-07-02 06:41:16.510 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.510 if eqi is None:
2025-07-02 06:41:16.510 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.510 atags = btags = ""
2025-07-02 06:41:16.510 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.510 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.510 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.510 if tag == 'replace':
2025-07-02 06:41:16.510 atags += '^' * la
2025-07-02 06:41:16.511 btags += '^' * lb
2025-07-02 06:41:16.511 elif tag == 'delete':
2025-07-02 06:41:16.511 atags += '-' * la
2025-07-02 06:41:16.511 elif tag == 'insert':
2025-07-02 06:41:16.511 btags += '+' * lb
2025-07-02 06:41:16.511 elif tag == 'equal':
2025-07-02 06:41:16.511 atags += ' ' * la
2025-07-02 06:41:16.511 btags += ' ' * lb
2025-07-02 06:41:16.511 else:
2025-07-02 06:41:16.511 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.511 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.511 else:
2025-07-02 06:41:16.511 # the synch pair is identical
2025-07-02 06:41:16.511 yield ' ' + aelt
2025-07-02 06:41:16.511
2025-07-02 06:41:16.511 # pump out diffs from after the synch point
2025-07-02 06:41:16.511 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.511
2025-07-02 06:41:16.511 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.512
2025-07-02 06:41:16.512 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.512 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.512 alo = 71, ahi = 1101
2025-07-02 06:41:16.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.512 blo = 71, bhi = 1101
2025-07-02 06:41:16.512
2025-07-02 06:41:16.512 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.512 g = []
2025-07-02 06:41:16.512 if alo < ahi:
2025-07-02 06:41:16.512 if blo < bhi:
2025-07-02 06:41:16.512 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.512 else:
2025-07-02 06:41:16.512 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.512 elif blo < bhi:
2025-07-02 06:41:16.512 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.512
2025-07-02 06:41:16.512 > yield from g
2025-07-02 06:41:16.512
2025-07-02 06:41:16.513 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.513 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.513 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.513 alo = 71, ahi = 1101
2025-07-02 06:41:16.513 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.513 blo = 71, bhi = 1101
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.513 r"""
2025-07-02 06:41:16.513 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.513 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.513 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.513 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513 Example:
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513 >>> d = Differ()
2025-07-02 06:41:16.513 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.514 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.514 >>> print(''.join(results), end="")
2025-07-02 06:41:16.514 - abcDefghiJkl
2025-07-02 06:41:16.514 + abcdefGhijkl
2025-07-02 06:41:16.514 """
2025-07-02 06:41:16.514
2025-07-02 06:41:16.514 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.514 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.514 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.514 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.514 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.514
2025-07-02 06:41:16.514 # search for the pair that matches best without being identical
2025-07-02 06:41:16.514 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.514 # on junk -- unless we have to)
2025-07-02 06:41:16.514 for j in range(blo, bhi):
2025-07-02 06:41:16.514 bj = b[j]
2025-07-02 06:41:16.514 cruncher.set_seq2(bj)
2025-07-02 06:41:16.515 for i in range(alo, ahi):
2025-07-02 06:41:16.515 ai = a[i]
2025-07-02 06:41:16.515 if ai == bj:
2025-07-02 06:41:16.515 if eqi is None:
2025-07-02 06:41:16.515 eqi, eqj = i, j
2025-07-02 06:41:16.515 continue
2025-07-02 06:41:16.515 cruncher.set_seq1(ai)
2025-07-02 06:41:16.515 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.515 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.515 # compares by a factor of 3.
2025-07-02 06:41:16.515 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.515 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.515 # of the computation is cached by cruncher
2025-07-02 06:41:16.515 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.515 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.515 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.515 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.515 if best_ratio < cutoff:
2025-07-02 06:41:16.515 # no non-identical "pretty close" pair
2025-07-02 06:41:16.515 if eqi is None:
2025-07-02 06:41:16.515 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.516 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.516 return
2025-07-02 06:41:16.516 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.516 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.516 else:
2025-07-02 06:41:16.516 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.516 eqi = None
2025-07-02 06:41:16.516
2025-07-02 06:41:16.516 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.516 # identical
2025-07-02 06:41:16.516
2025-07-02 06:41:16.516 # pump out diffs from before the synch point
2025-07-02 06:41:16.516 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.516
2025-07-02 06:41:16.516 # do intraline marking on the synch pair
2025-07-02 06:41:16.516 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.516 if eqi is None:
2025-07-02 06:41:16.516 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.516 atags = btags = ""
2025-07-02 06:41:16.516 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.517 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.517 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.517 if tag == 'replace':
2025-07-02 06:41:16.517 atags += '^' * la
2025-07-02 06:41:16.517 btags += '^' * lb
2025-07-02 06:41:16.517 elif tag == 'delete':
2025-07-02 06:41:16.517 atags += '-' * la
2025-07-02 06:41:16.517 elif tag == 'insert':
2025-07-02 06:41:16.517 btags += '+' * lb
2025-07-02 06:41:16.517 elif tag == 'equal':
2025-07-02 06:41:16.517 atags += ' ' * la
2025-07-02 06:41:16.517 btags += ' ' * lb
2025-07-02 06:41:16.517 else:
2025-07-02 06:41:16.517 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.517 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.517 else:
2025-07-02 06:41:16.517 # the synch pair is identical
2025-07-02 06:41:16.517 yield ' ' + aelt
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518 # pump out diffs from after the synch point
2025-07-02 06:41:16.518 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.518 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.518 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.518 alo = 72, ahi = 1101
2025-07-02 06:41:16.518 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.518 blo = 72, bhi = 1101
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.518 g = []
2025-07-02 06:41:16.518 if alo < ahi:
2025-07-02 06:41:16.518 if blo < bhi:
2025-07-02 06:41:16.518 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.518 else:
2025-07-02 06:41:16.518 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.519 elif blo < bhi:
2025-07-02 06:41:16.519 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 > yield from g
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.519 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.519 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.519 alo = 72, ahi = 1101
2025-07-02 06:41:16.519 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.519 blo = 72, bhi = 1101
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.519 r"""
2025-07-02 06:41:16.519 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.519 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.519 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.519 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.519
2025-07-02 06:41:16.520 Example:
2025-07-02 06:41:16.520
2025-07-02 06:41:16.520 >>> d = Differ()
2025-07-02 06:41:16.520 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.520 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.520 >>> print(''.join(results), end="")
2025-07-02 06:41:16.520 - abcDefghiJkl
2025-07-02 06:41:16.520 + abcdefGhijkl
2025-07-02 06:41:16.520 """
2025-07-02 06:41:16.520
2025-07-02 06:41:16.520 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.520 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.520 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.520 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.520 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.520
2025-07-02 06:41:16.520 # search for the pair that matches best without being identical
2025-07-02 06:41:16.521 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.521 # on junk -- unless we have to)
2025-07-02 06:41:16.521 for j in range(blo, bhi):
2025-07-02 06:41:16.521 bj = b[j]
2025-07-02 06:41:16.521 cruncher.set_seq2(bj)
2025-07-02 06:41:16.521 for i in range(alo, ahi):
2025-07-02 06:41:16.521 ai = a[i]
2025-07-02 06:41:16.521 if ai == bj:
2025-07-02 06:41:16.521 if eqi is None:
2025-07-02 06:41:16.521 eqi, eqj = i, j
2025-07-02 06:41:16.521 continue
2025-07-02 06:41:16.521 cruncher.set_seq1(ai)
2025-07-02 06:41:16.521 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.521 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.521 # compares by a factor of 3.
2025-07-02 06:41:16.521 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.521 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.521 # of the computation is cached by cruncher
2025-07-02 06:41:16.521 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.522 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.522 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.522 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.522 if best_ratio < cutoff:
2025-07-02 06:41:16.522 # no non-identical "pretty close" pair
2025-07-02 06:41:16.522 if eqi is None:
2025-07-02 06:41:16.522 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.522 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.522 return
2025-07-02 06:41:16.522 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.522 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.522 else:
2025-07-02 06:41:16.522 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.522 eqi = None
2025-07-02 06:41:16.522
2025-07-02 06:41:16.522 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.522 # identical
2025-07-02 06:41:16.522
2025-07-02 06:41:16.522 # pump out diffs from before the synch point
2025-07-02 06:41:16.522 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.522
2025-07-02 06:41:16.523 # do intraline marking on the synch pair
2025-07-02 06:41:16.523 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.523 if eqi is None:
2025-07-02 06:41:16.523 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.523 atags = btags = ""
2025-07-02 06:41:16.523 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.523 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.523 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.523 if tag == 'replace':
2025-07-02 06:41:16.523 atags += '^' * la
2025-07-02 06:41:16.523 btags += '^' * lb
2025-07-02 06:41:16.523 elif tag == 'delete':
2025-07-02 06:41:16.523 atags += '-' * la
2025-07-02 06:41:16.523 elif tag == 'insert':
2025-07-02 06:41:16.523 btags += '+' * lb
2025-07-02 06:41:16.523 elif tag == 'equal':
2025-07-02 06:41:16.523 atags += ' ' * la
2025-07-02 06:41:16.523 btags += ' ' * lb
2025-07-02 06:41:16.524 else:
2025-07-02 06:41:16.524 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.524 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.524 else:
2025-07-02 06:41:16.524 # the synch pair is identical
2025-07-02 06:41:16.524 yield ' ' + aelt
2025-07-02 06:41:16.524
2025-07-02 06:41:16.524 # pump out diffs from after the synch point
2025-07-02 06:41:16.524 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.524
2025-07-02 06:41:16.524 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.524 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.524
2025-07-02 06:41:16.524 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.524 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.524 alo = 73, ahi = 1101
2025-07-02 06:41:16.524 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.524 blo = 73, bhi = 1101
2025-07-02 06:41:16.524
2025-07-02 06:41:16.525 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.525 g = []
2025-07-02 06:41:16.525 if alo < ahi:
2025-07-02 06:41:16.525 if blo < bhi:
2025-07-02 06:41:16.525 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.525 else:
2025-07-02 06:41:16.525 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.525 elif blo < bhi:
2025-07-02 06:41:16.525 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.525
2025-07-02 06:41:16.525 > yield from g
2025-07-02 06:41:16.525
2025-07-02 06:41:16.525 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.525 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.525
2025-07-02 06:41:16.525 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.525 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.525 alo = 73, ahi = 1101
2025-07-02 06:41:16.525 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.526 blo = 73, bhi = 1101
2025-07-02 06:41:16.526
2025-07-02 06:41:16.526 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.526 r"""
2025-07-02 06:41:16.526 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.526 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.526 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.526 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.526
2025-07-02 06:41:16.526 Example:
2025-07-02 06:41:16.526
2025-07-02 06:41:16.526 >>> d = Differ()
2025-07-02 06:41:16.526 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.527 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.527 >>> print(''.join(results), end="")
2025-07-02 06:41:16.527 - abcDefghiJkl
2025-07-02 06:41:16.527 + abcdefGhijkl
2025-07-02 06:41:16.527 """
2025-07-02 06:41:16.527
2025-07-02 06:41:16.527 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.527 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.527 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.527 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.527 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.527
2025-07-02 06:41:16.527 # search for the pair that matches best without being identical
2025-07-02 06:41:16.527 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.527 # on junk -- unless we have to)
2025-07-02 06:41:16.527 for j in range(blo, bhi):
2025-07-02 06:41:16.527 bj = b[j]
2025-07-02 06:41:16.528 cruncher.set_seq2(bj)
2025-07-02 06:41:16.528 for i in range(alo, ahi):
2025-07-02 06:41:16.528 ai = a[i]
2025-07-02 06:41:16.528 if ai == bj:
2025-07-02 06:41:16.528 if eqi is None:
2025-07-02 06:41:16.528 eqi, eqj = i, j
2025-07-02 06:41:16.528 continue
2025-07-02 06:41:16.528 cruncher.set_seq1(ai)
2025-07-02 06:41:16.528 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.528 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.528 # compares by a factor of 3.
2025-07-02 06:41:16.528 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.528 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.528 # of the computation is cached by cruncher
2025-07-02 06:41:16.528 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.528 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.528 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.528 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.528 if best_ratio < cutoff:
2025-07-02 06:41:16.528 # no non-identical "pretty close" pair
2025-07-02 06:41:16.529 if eqi is None:
2025-07-02 06:41:16.529 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.529 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.529 return
2025-07-02 06:41:16.529 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.529 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.529 else:
2025-07-02 06:41:16.529 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.529 eqi = None
2025-07-02 06:41:16.529
2025-07-02 06:41:16.529 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.529 # identical
2025-07-02 06:41:16.529
2025-07-02 06:41:16.529 # pump out diffs from before the synch point
2025-07-02 06:41:16.529 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.529
2025-07-02 06:41:16.529 # do intraline marking on the synch pair
2025-07-02 06:41:16.529 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.530 if eqi is None:
2025-07-02 06:41:16.530 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.530 atags = btags = ""
2025-07-02 06:41:16.530 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.530 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.530 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.530 if tag == 'replace':
2025-07-02 06:41:16.530 atags += '^' * la
2025-07-02 06:41:16.530 btags += '^' * lb
2025-07-02 06:41:16.530 elif tag == 'delete':
2025-07-02 06:41:16.530 atags += '-' * la
2025-07-02 06:41:16.530 elif tag == 'insert':
2025-07-02 06:41:16.530 btags += '+' * lb
2025-07-02 06:41:16.530 elif tag == 'equal':
2025-07-02 06:41:16.530 atags += ' ' * la
2025-07-02 06:41:16.530 btags += ' ' * lb
2025-07-02 06:41:16.530 else:
2025-07-02 06:41:16.530 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.530 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.530 else:
2025-07-02 06:41:16.530 # the synch pair is identical
2025-07-02 06:41:16.530 yield ' ' + aelt
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531 # pump out diffs from after the synch point
2025-07-02 06:41:16.531 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.531 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.531 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.531 alo = 74, ahi = 1101
2025-07-02 06:41:16.531 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.531 blo = 74, bhi = 1101
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.531 g = []
2025-07-02 06:41:16.531 if alo < ahi:
2025-07-02 06:41:16.531 if blo < bhi:
2025-07-02 06:41:16.531 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.531 else:
2025-07-02 06:41:16.531 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.532 elif blo < bhi:
2025-07-02 06:41:16.532 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 > yield from g
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.532 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.532 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.532 alo = 74, ahi = 1101
2025-07-02 06:41:16.532 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.532 blo = 74, bhi = 1101
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.532 r"""
2025-07-02 06:41:16.532 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.532 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.532 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.532 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533 Example:
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533 >>> d = Differ()
2025-07-02 06:41:16.533 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.533 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.533 >>> print(''.join(results), end="")
2025-07-02 06:41:16.533 - abcDefghiJkl
2025-07-02 06:41:16.533 + abcdefGhijkl
2025-07-02 06:41:16.533 """
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.533 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.533 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.533 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.533 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533 # search for the pair that matches best without being identical
2025-07-02 06:41:16.533 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.534 # on junk -- unless we have to)
2025-07-02 06:41:16.534 for j in range(blo, bhi):
2025-07-02 06:41:16.534 bj = b[j]
2025-07-02 06:41:16.534 cruncher.set_seq2(bj)
2025-07-02 06:41:16.534 for i in range(alo, ahi):
2025-07-02 06:41:16.534 ai = a[i]
2025-07-02 06:41:16.534 if ai == bj:
2025-07-02 06:41:16.534 if eqi is None:
2025-07-02 06:41:16.534 eqi, eqj = i, j
2025-07-02 06:41:16.534 continue
2025-07-02 06:41:16.534 cruncher.set_seq1(ai)
2025-07-02 06:41:16.534 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.534 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.534 # compares by a factor of 3.
2025-07-02 06:41:16.534 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.534 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.534 # of the computation is cached by cruncher
2025-07-02 06:41:16.534 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.534 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.534 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.535 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.535 if best_ratio < cutoff:
2025-07-02 06:41:16.535 # no non-identical "pretty close" pair
2025-07-02 06:41:16.535 if eqi is None:
2025-07-02 06:41:16.535 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.535 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.535 return
2025-07-02 06:41:16.535 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.535 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.535 else:
2025-07-02 06:41:16.535 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.535 eqi = None
2025-07-02 06:41:16.535
2025-07-02 06:41:16.535 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.535 # identical
2025-07-02 06:41:16.535
2025-07-02 06:41:16.535 # pump out diffs from before the synch point
2025-07-02 06:41:16.535 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.535
2025-07-02 06:41:16.536 # do intraline marking on the synch pair
2025-07-02 06:41:16.536 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.536 if eqi is None:
2025-07-02 06:41:16.536 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.536 atags = btags = ""
2025-07-02 06:41:16.536 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.536 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.536 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.536 if tag == 'replace':
2025-07-02 06:41:16.536 atags += '^' * la
2025-07-02 06:41:16.536 btags += '^' * lb
2025-07-02 06:41:16.536 elif tag == 'delete':
2025-07-02 06:41:16.536 atags += '-' * la
2025-07-02 06:41:16.536 elif tag == 'insert':
2025-07-02 06:41:16.536 btags += '+' * lb
2025-07-02 06:41:16.536 elif tag == 'equal':
2025-07-02 06:41:16.536 atags += ' ' * la
2025-07-02 06:41:16.536 btags += ' ' * lb
2025-07-02 06:41:16.536 else:
2025-07-02 06:41:16.537 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.537 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.537 else:
2025-07-02 06:41:16.537 # the synch pair is identical
2025-07-02 06:41:16.537 yield ' ' + aelt
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537 # pump out diffs from after the synch point
2025-07-02 06:41:16.537 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.537 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.537 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.537 alo = 75, ahi = 1101
2025-07-02 06:41:16.537 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.537 blo = 75, bhi = 1101
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.537 g = []
2025-07-02 06:41:16.538 if alo < ahi:
2025-07-02 06:41:16.538 if blo < bhi:
2025-07-02 06:41:16.538 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.538 else:
2025-07-02 06:41:16.538 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.538 elif blo < bhi:
2025-07-02 06:41:16.538 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.538
2025-07-02 06:41:16.538 > yield from g
2025-07-02 06:41:16.538
2025-07-02 06:41:16.538 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.538 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.538
2025-07-02 06:41:16.538 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.538 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.538 alo = 75, ahi = 1101
2025-07-02 06:41:16.538 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.539 blo = 75, bhi = 1101
2025-07-02 06:41:16.539
2025-07-02 06:41:16.539 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.539 r"""
2025-07-02 06:41:16.539 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.539 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.539 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.539 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.539
2025-07-02 06:41:16.539 Example:
2025-07-02 06:41:16.539
2025-07-02 06:41:16.539 >>> d = Differ()
2025-07-02 06:41:16.539 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.539 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.539 >>> print(''.join(results), end="")
2025-07-02 06:41:16.539 - abcDefghiJkl
2025-07-02 06:41:16.539 + abcdefGhijkl
2025-07-02 06:41:16.540 """
2025-07-02 06:41:16.540
2025-07-02 06:41:16.540 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.540 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.540 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.540 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.540 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.540
2025-07-02 06:41:16.540 # search for the pair that matches best without being identical
2025-07-02 06:41:16.540 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.540 # on junk -- unless we have to)
2025-07-02 06:41:16.540 for j in range(blo, bhi):
2025-07-02 06:41:16.540 bj = b[j]
2025-07-02 06:41:16.540 cruncher.set_seq2(bj)
2025-07-02 06:41:16.540 for i in range(alo, ahi):
2025-07-02 06:41:16.540 ai = a[i]
2025-07-02 06:41:16.540 if ai == bj:
2025-07-02 06:41:16.540 if eqi is None:
2025-07-02 06:41:16.540 eqi, eqj = i, j
2025-07-02 06:41:16.540 continue
2025-07-02 06:41:16.541 cruncher.set_seq1(ai)
2025-07-02 06:41:16.541 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.541 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.541 # compares by a factor of 3.
2025-07-02 06:41:16.541 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.541 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.541 # of the computation is cached by cruncher
2025-07-02 06:41:16.541 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.541 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.541 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.541 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.541 if best_ratio < cutoff:
2025-07-02 06:41:16.541 # no non-identical "pretty close" pair
2025-07-02 06:41:16.541 if eqi is None:
2025-07-02 06:41:16.541 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.541 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.541 return
2025-07-02 06:41:16.541 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.541 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.541 else:
2025-07-02 06:41:16.542 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.542 eqi = None
2025-07-02 06:41:16.542
2025-07-02 06:41:16.542 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.542 # identical
2025-07-02 06:41:16.542
2025-07-02 06:41:16.542 # pump out diffs from before the synch point
2025-07-02 06:41:16.542 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.542
2025-07-02 06:41:16.542 # do intraline marking on the synch pair
2025-07-02 06:41:16.542 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.542 if eqi is None:
2025-07-02 06:41:16.542 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.542 atags = btags = ""
2025-07-02 06:41:16.542 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.542 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.542 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.542 if tag == 'replace':
2025-07-02 06:41:16.542 atags += '^' * la
2025-07-02 06:41:16.542 btags += '^' * lb
2025-07-02 06:41:16.542 elif tag == 'delete':
2025-07-02 06:41:16.543 atags += '-' * la
2025-07-02 06:41:16.543 elif tag == 'insert':
2025-07-02 06:41:16.543 btags += '+' * lb
2025-07-02 06:41:16.543 elif tag == 'equal':
2025-07-02 06:41:16.543 atags += ' ' * la
2025-07-02 06:41:16.543 btags += ' ' * lb
2025-07-02 06:41:16.543 else:
2025-07-02 06:41:16.543 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.543 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.543 else:
2025-07-02 06:41:16.543 # the synch pair is identical
2025-07-02 06:41:16.543 yield ' ' + aelt
2025-07-02 06:41:16.543
2025-07-02 06:41:16.543 # pump out diffs from after the synch point
2025-07-02 06:41:16.543 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.543
2025-07-02 06:41:16.543 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.543 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.543
2025-07-02 06:41:16.543 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.544 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.544 alo = 76, ahi = 1101
2025-07-02 06:41:16.544 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.544 blo = 76, bhi = 1101
2025-07-02 06:41:16.544
2025-07-02 06:41:16.544 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.544 g = []
2025-07-02 06:41:16.544 if alo < ahi:
2025-07-02 06:41:16.544 if blo < bhi:
2025-07-02 06:41:16.544 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.544 else:
2025-07-02 06:41:16.544 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.544 elif blo < bhi:
2025-07-02 06:41:16.544 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.544
2025-07-02 06:41:16.544 > yield from g
2025-07-02 06:41:16.544
2025-07-02 06:41:16.544 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.544 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.544
2025-07-02 06:41:16.545 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.545 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.545 alo = 76, ahi = 1101
2025-07-02 06:41:16.545 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.545 blo = 76, bhi = 1101
2025-07-02 06:41:16.545
2025-07-02 06:41:16.545 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.545 r"""
2025-07-02 06:41:16.545 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.545 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.545 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.545 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.545
2025-07-02 06:41:16.545 Example:
2025-07-02 06:41:16.545
2025-07-02 06:41:16.545 >>> d = Differ()
2025-07-02 06:41:16.545 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.545 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.545 >>> print(''.join(results), end="")
2025-07-02 06:41:16.545 - abcDefghiJkl
2025-07-02 06:41:16.546 + abcdefGhijkl
2025-07-02 06:41:16.546 """
2025-07-02 06:41:16.546
2025-07-02 06:41:16.546 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.546 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.546 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.546 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.546 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.546
2025-07-02 06:41:16.546 # search for the pair that matches best without being identical
2025-07-02 06:41:16.546 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.546 # on junk -- unless we have to)
2025-07-02 06:41:16.546 for j in range(blo, bhi):
2025-07-02 06:41:16.546 bj = b[j]
2025-07-02 06:41:16.546 cruncher.set_seq2(bj)
2025-07-02 06:41:16.546 for i in range(alo, ahi):
2025-07-02 06:41:16.546 ai = a[i]
2025-07-02 06:41:16.546 if ai == bj:
2025-07-02 06:41:16.546 if eqi is None:
2025-07-02 06:41:16.547 eqi, eqj = i, j
2025-07-02 06:41:16.547 continue
2025-07-02 06:41:16.547 cruncher.set_seq1(ai)
2025-07-02 06:41:16.547 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.547 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.547 # compares by a factor of 3.
2025-07-02 06:41:16.547 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.547 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.547 # of the computation is cached by cruncher
2025-07-02 06:41:16.547 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.547 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.547 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.547 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.547 if best_ratio < cutoff:
2025-07-02 06:41:16.547 # no non-identical "pretty close" pair
2025-07-02 06:41:16.547 if eqi is None:
2025-07-02 06:41:16.547 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.548 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.548 return
2025-07-02 06:41:16.548 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.548 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.548 else:
2025-07-02 06:41:16.548 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.548 eqi = None
2025-07-02 06:41:16.548
2025-07-02 06:41:16.548 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.548 # identical
2025-07-02 06:41:16.548
2025-07-02 06:41:16.548 # pump out diffs from before the synch point
2025-07-02 06:41:16.548 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.548
2025-07-02 06:41:16.548 # do intraline marking on the synch pair
2025-07-02 06:41:16.548 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.548 if eqi is None:
2025-07-02 06:41:16.548 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.548 atags = btags = ""
2025-07-02 06:41:16.548 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.549 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.549 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.549 if tag == 'replace':
2025-07-02 06:41:16.549 atags += '^' * la
2025-07-02 06:41:16.549 btags += '^' * lb
2025-07-02 06:41:16.549 elif tag == 'delete':
2025-07-02 06:41:16.549 atags += '-' * la
2025-07-02 06:41:16.549 elif tag == 'insert':
2025-07-02 06:41:16.549 btags += '+' * lb
2025-07-02 06:41:16.549 elif tag == 'equal':
2025-07-02 06:41:16.549 atags += ' ' * la
2025-07-02 06:41:16.549 btags += ' ' * lb
2025-07-02 06:41:16.549 else:
2025-07-02 06:41:16.549 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.549 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.549 else:
2025-07-02 06:41:16.549 # the synch pair is identical
2025-07-02 06:41:16.549 yield ' ' + aelt
2025-07-02 06:41:16.549
2025-07-02 06:41:16.549 # pump out diffs from after the synch point
2025-07-02 06:41:16.550 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.550
2025-07-02 06:41:16.550 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.550 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.550
2025-07-02 06:41:16.550 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.550 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.550 alo = 77, ahi = 1101
2025-07-02 06:41:16.550 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.550 blo = 77, bhi = 1101
2025-07-02 06:41:16.550
2025-07-02 06:41:16.550 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.550 g = []
2025-07-02 06:41:16.550 if alo < ahi:
2025-07-02 06:41:16.550 if blo < bhi:
2025-07-02 06:41:16.550 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.550 else:
2025-07-02 06:41:16.550 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.550 elif blo < bhi:
2025-07-02 06:41:16.550 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 > yield from g
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.551 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.551 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.551 alo = 77, ahi = 1101
2025-07-02 06:41:16.551 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.551 blo = 77, bhi = 1101
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.551 r"""
2025-07-02 06:41:16.551 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.551 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.551 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.551 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 Example:
2025-07-02 06:41:16.552
2025-07-02 06:41:16.552 >>> d = Differ()
2025-07-02 06:41:16.552 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.552 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.552 >>> print(''.join(results), end="")
2025-07-02 06:41:16.552 - abcDefghiJkl
2025-07-02 06:41:16.552 + abcdefGhijkl
2025-07-02 06:41:16.552 """
2025-07-02 06:41:16.552
2025-07-02 06:41:16.552 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.552 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.552 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.552 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.552 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.552
2025-07-02 06:41:16.552 # search for the pair that matches best without being identical
2025-07-02 06:41:16.552 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.552 # on junk -- unless we have to)
2025-07-02 06:41:16.553 for j in range(blo, bhi):
2025-07-02 06:41:16.553 bj = b[j]
2025-07-02 06:41:16.553 cruncher.set_seq2(bj)
2025-07-02 06:41:16.553 for i in range(alo, ahi):
2025-07-02 06:41:16.553 ai = a[i]
2025-07-02 06:41:16.553 if ai == bj:
2025-07-02 06:41:16.553 if eqi is None:
2025-07-02 06:41:16.553 eqi, eqj = i, j
2025-07-02 06:41:16.553 continue
2025-07-02 06:41:16.553 cruncher.set_seq1(ai)
2025-07-02 06:41:16.553 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.553 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.553 # compares by a factor of 3.
2025-07-02 06:41:16.553 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.553 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.553 # of the computation is cached by cruncher
2025-07-02 06:41:16.553 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.553 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.553 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.553 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.554 if best_ratio < cutoff:
2025-07-02 06:41:16.554 # no non-identical "pretty close" pair
2025-07-02 06:41:16.554 if eqi is None:
2025-07-02 06:41:16.554 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.554 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.554 return
2025-07-02 06:41:16.554 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.554 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.554 else:
2025-07-02 06:41:16.554 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.554 eqi = None
2025-07-02 06:41:16.554
2025-07-02 06:41:16.554 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.554 # identical
2025-07-02 06:41:16.554
2025-07-02 06:41:16.554 # pump out diffs from before the synch point
2025-07-02 06:41:16.554 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.554
2025-07-02 06:41:16.554 # do intraline marking on the synch pair
2025-07-02 06:41:16.554 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.554 if eqi is None:
2025-07-02 06:41:16.555 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.555 atags = btags = ""
2025-07-02 06:41:16.555 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.555 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.555 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.555 if tag == 'replace':
2025-07-02 06:41:16.555 atags += '^' * la
2025-07-02 06:41:16.555 btags += '^' * lb
2025-07-02 06:41:16.555 elif tag == 'delete':
2025-07-02 06:41:16.555 atags += '-' * la
2025-07-02 06:41:16.555 elif tag == 'insert':
2025-07-02 06:41:16.555 btags += '+' * lb
2025-07-02 06:41:16.555 elif tag == 'equal':
2025-07-02 06:41:16.555 atags += ' ' * la
2025-07-02 06:41:16.555 btags += ' ' * lb
2025-07-02 06:41:16.555 else:
2025-07-02 06:41:16.555 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.556 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.556 else:
2025-07-02 06:41:16.556 # the synch pair is identical
2025-07-02 06:41:16.556 yield ' ' + aelt
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556 # pump out diffs from after the synch point
2025-07-02 06:41:16.556 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.556 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.556 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.556 alo = 78, ahi = 1101
2025-07-02 06:41:16.556 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.556 blo = 78, bhi = 1101
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.556 g = []
2025-07-02 06:41:16.556 if alo < ahi:
2025-07-02 06:41:16.557 if blo < bhi:
2025-07-02 06:41:16.557 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.557 else:
2025-07-02 06:41:16.557 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.557 elif blo < bhi:
2025-07-02 06:41:16.557 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.557
2025-07-02 06:41:16.557 > yield from g
2025-07-02 06:41:16.557
2025-07-02 06:41:16.557 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.557 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.557
2025-07-02 06:41:16.557 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.557 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.557 alo = 78, ahi = 1101
2025-07-02 06:41:16.557 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.558 blo = 78, bhi = 1101
2025-07-02 06:41:16.558
2025-07-02 06:41:16.558 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.558 r"""
2025-07-02 06:41:16.558 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.558 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.558 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.558 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.558
2025-07-02 06:41:16.558 Example:
2025-07-02 06:41:16.558
2025-07-02 06:41:16.558 >>> d = Differ()
2025-07-02 06:41:16.558 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.558 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.558 >>> print(''.join(results), end="")
2025-07-02 06:41:16.558 - abcDefghiJkl
2025-07-02 06:41:16.558 + abcdefGhijkl
2025-07-02 06:41:16.559 """
2025-07-02 06:41:16.559
2025-07-02 06:41:16.559 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.559 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.559 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.559 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.559 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.559
2025-07-02 06:41:16.559 # search for the pair that matches best without being identical
2025-07-02 06:41:16.559 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.559 # on junk -- unless we have to)
2025-07-02 06:41:16.559 for j in range(blo, bhi):
2025-07-02 06:41:16.559 bj = b[j]
2025-07-02 06:41:16.559 cruncher.set_seq2(bj)
2025-07-02 06:41:16.559 for i in range(alo, ahi):
2025-07-02 06:41:16.559 ai = a[i]
2025-07-02 06:41:16.559 if ai == bj:
2025-07-02 06:41:16.559 if eqi is None:
2025-07-02 06:41:16.559 eqi, eqj = i, j
2025-07-02 06:41:16.559 continue
2025-07-02 06:41:16.559 cruncher.set_seq1(ai)
2025-07-02 06:41:16.560 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.560 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.560 # compares by a factor of 3.
2025-07-02 06:41:16.560 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.560 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.560 # of the computation is cached by cruncher
2025-07-02 06:41:16.560 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.560 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.560 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.560 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.560 if best_ratio < cutoff:
2025-07-02 06:41:16.560 # no non-identical "pretty close" pair
2025-07-02 06:41:16.560 if eqi is None:
2025-07-02 06:41:16.560 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.560 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.560 return
2025-07-02 06:41:16.560 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.560 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.560 else:
2025-07-02 06:41:16.560 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.561 eqi = None
2025-07-02 06:41:16.561
2025-07-02 06:41:16.561 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.561 # identical
2025-07-02 06:41:16.561
2025-07-02 06:41:16.561 # pump out diffs from before the synch point
2025-07-02 06:41:16.561 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.561
2025-07-02 06:41:16.561 # do intraline marking on the synch pair
2025-07-02 06:41:16.561 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.561 if eqi is None:
2025-07-02 06:41:16.561 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.561 atags = btags = ""
2025-07-02 06:41:16.561 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.561 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.561 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.561 if tag == 'replace':
2025-07-02 06:41:16.561 atags += '^' * la
2025-07-02 06:41:16.561 btags += '^' * lb
2025-07-02 06:41:16.561 elif tag == 'delete':
2025-07-02 06:41:16.562 atags += '-' * la
2025-07-02 06:41:16.562 elif tag == 'insert':
2025-07-02 06:41:16.562 btags += '+' * lb
2025-07-02 06:41:16.562 elif tag == 'equal':
2025-07-02 06:41:16.562 atags += ' ' * la
2025-07-02 06:41:16.562 btags += ' ' * lb
2025-07-02 06:41:16.562 else:
2025-07-02 06:41:16.562 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.562 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.562 else:
2025-07-02 06:41:16.562 # the synch pair is identical
2025-07-02 06:41:16.562 yield ' ' + aelt
2025-07-02 06:41:16.562
2025-07-02 06:41:16.562 # pump out diffs from after the synch point
2025-07-02 06:41:16.562 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.562
2025-07-02 06:41:16.562 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.562 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.562
2025-07-02 06:41:16.562 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.562 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.563 alo = 79, ahi = 1101
2025-07-02 06:41:16.563 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.563 blo = 79, bhi = 1101
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.563 g = []
2025-07-02 06:41:16.563 if alo < ahi:
2025-07-02 06:41:16.563 if blo < bhi:
2025-07-02 06:41:16.563 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.563 else:
2025-07-02 06:41:16.563 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.563 elif blo < bhi:
2025-07-02 06:41:16.563 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 > yield from g
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.563 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.564 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.564 alo = 79, ahi = 1101
2025-07-02 06:41:16.564 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.564 blo = 79, bhi = 1101
2025-07-02 06:41:16.564
2025-07-02 06:41:16.564 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.564 r"""
2025-07-02 06:41:16.564 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.564 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.564 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.564 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.564
2025-07-02 06:41:16.564 Example:
2025-07-02 06:41:16.564
2025-07-02 06:41:16.564 >>> d = Differ()
2025-07-02 06:41:16.564 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.564 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.565 >>> print(''.join(results), end="")
2025-07-02 06:41:16.565 - abcDefghiJkl
2025-07-02 06:41:16.565 + abcdefGhijkl
2025-07-02 06:41:16.565 """
2025-07-02 06:41:16.565
2025-07-02 06:41:16.565 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.565 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.565 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.565 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.565 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.565
2025-07-02 06:41:16.565 # search for the pair that matches best without being identical
2025-07-02 06:41:16.565 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.565 # on junk -- unless we have to)
2025-07-02 06:41:16.565 for j in range(blo, bhi):
2025-07-02 06:41:16.565 bj = b[j]
2025-07-02 06:41:16.565 cruncher.set_seq2(bj)
2025-07-02 06:41:16.565 for i in range(alo, ahi):
2025-07-02 06:41:16.566 ai = a[i]
2025-07-02 06:41:16.566 if ai == bj:
2025-07-02 06:41:16.566 if eqi is None:
2025-07-02 06:41:16.566 eqi, eqj = i, j
2025-07-02 06:41:16.566 continue
2025-07-02 06:41:16.566 cruncher.set_seq1(ai)
2025-07-02 06:41:16.566 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.566 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.566 # compares by a factor of 3.
2025-07-02 06:41:16.566 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.566 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.566 # of the computation is cached by cruncher
2025-07-02 06:41:16.566 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.566 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.566 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.566 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.566 if best_ratio < cutoff:
2025-07-02 06:41:16.566 # no non-identical "pretty close" pair
2025-07-02 06:41:16.566 if eqi is None:
2025-07-02 06:41:16.567 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.567 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.567 return
2025-07-02 06:41:16.567 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.567 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.567 else:
2025-07-02 06:41:16.567 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.567 eqi = None
2025-07-02 06:41:16.567
2025-07-02 06:41:16.567 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.567 # identical
2025-07-02 06:41:16.567
2025-07-02 06:41:16.567 # pump out diffs from before the synch point
2025-07-02 06:41:16.567 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.567
2025-07-02 06:41:16.567 # do intraline marking on the synch pair
2025-07-02 06:41:16.567 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.567 if eqi is None:
2025-07-02 06:41:16.567 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.567 atags = btags = ""
2025-07-02 06:41:16.567 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.568 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.568 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.568 if tag == 'replace':
2025-07-02 06:41:16.568 atags += '^' * la
2025-07-02 06:41:16.568 btags += '^' * lb
2025-07-02 06:41:16.568 elif tag == 'delete':
2025-07-02 06:41:16.568 atags += '-' * la
2025-07-02 06:41:16.568 elif tag == 'insert':
2025-07-02 06:41:16.568 btags += '+' * lb
2025-07-02 06:41:16.568 elif tag == 'equal':
2025-07-02 06:41:16.568 atags += ' ' * la
2025-07-02 06:41:16.568 btags += ' ' * lb
2025-07-02 06:41:16.568 else:
2025-07-02 06:41:16.568 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.568 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.568 else:
2025-07-02 06:41:16.568 # the synch pair is identical
2025-07-02 06:41:16.568 yield ' ' + aelt
2025-07-02 06:41:16.568
2025-07-02 06:41:16.568 # pump out diffs from after the synch point
2025-07-02 06:41:16.569 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.569
2025-07-02 06:41:16.569 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.569 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.569
2025-07-02 06:41:16.569 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.569 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.569 alo = 80, ahi = 1101
2025-07-02 06:41:16.569 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.569 blo = 80, bhi = 1101
2025-07-02 06:41:16.569
2025-07-02 06:41:16.569 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.569 g = []
2025-07-02 06:41:16.569 if alo < ahi:
2025-07-02 06:41:16.569 if blo < bhi:
2025-07-02 06:41:16.569 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.569 else:
2025-07-02 06:41:16.569 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.569 elif blo < bhi:
2025-07-02 06:41:16.569 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 > yield from g
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.570 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.570 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.570 alo = 80, ahi = 1101
2025-07-02 06:41:16.570 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.570 blo = 80, bhi = 1101
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.570 r"""
2025-07-02 06:41:16.570 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.570 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.570 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.570 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.571
2025-07-02 06:41:16.571 Example:
2025-07-02 06:41:16.571
2025-07-02 06:41:16.571 >>> d = Differ()
2025-07-02 06:41:16.571 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.571 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.571 >>> print(''.join(results), end="")
2025-07-02 06:41:16.571 - abcDefghiJkl
2025-07-02 06:41:16.571 + abcdefGhijkl
2025-07-02 06:41:16.571 """
2025-07-02 06:41:16.571
2025-07-02 06:41:16.571 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.571 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.571 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.571 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.571 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.571
2025-07-02 06:41:16.572 # search for the pair that matches best without being identical
2025-07-02 06:41:16.572 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.572 # on junk -- unless we have to)
2025-07-02 06:41:16.572 for j in range(blo, bhi):
2025-07-02 06:41:16.572 bj = b[j]
2025-07-02 06:41:16.572 cruncher.set_seq2(bj)
2025-07-02 06:41:16.572 for i in range(alo, ahi):
2025-07-02 06:41:16.572 ai = a[i]
2025-07-02 06:41:16.572 if ai == bj:
2025-07-02 06:41:16.572 if eqi is None:
2025-07-02 06:41:16.572 eqi, eqj = i, j
2025-07-02 06:41:16.572 continue
2025-07-02 06:41:16.572 cruncher.set_seq1(ai)
2025-07-02 06:41:16.572 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.572 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.572 # compares by a factor of 3.
2025-07-02 06:41:16.572 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.572 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.572 # of the computation is cached by cruncher
2025-07-02 06:41:16.572 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.573 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.573 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.573 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.573 if best_ratio < cutoff:
2025-07-02 06:41:16.573 # no non-identical "pretty close" pair
2025-07-02 06:41:16.573 if eqi is None:
2025-07-02 06:41:16.573 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.573 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.573 return
2025-07-02 06:41:16.573 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.573 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.573 else:
2025-07-02 06:41:16.573 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.573 eqi = None
2025-07-02 06:41:16.573
2025-07-02 06:41:16.573 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.573 # identical
2025-07-02 06:41:16.573
2025-07-02 06:41:16.574 # pump out diffs from before the synch point
2025-07-02 06:41:16.574 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.574
2025-07-02 06:41:16.574 # do intraline marking on the synch pair
2025-07-02 06:41:16.574 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.574 if eqi is None:
2025-07-02 06:41:16.574 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.574 atags = btags = ""
2025-07-02 06:41:16.574 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.574 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.574 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.574 if tag == 'replace':
2025-07-02 06:41:16.574 atags += '^' * la
2025-07-02 06:41:16.574 btags += '^' * lb
2025-07-02 06:41:16.574 elif tag == 'delete':
2025-07-02 06:41:16.574 atags += '-' * la
2025-07-02 06:41:16.574 elif tag == 'insert':
2025-07-02 06:41:16.574 btags += '+' * lb
2025-07-02 06:41:16.574 elif tag == 'equal':
2025-07-02 06:41:16.574 atags += ' ' * la
2025-07-02 06:41:16.575 btags += ' ' * lb
2025-07-02 06:41:16.575 else:
2025-07-02 06:41:16.575 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.575 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.575 else:
2025-07-02 06:41:16.575 # the synch pair is identical
2025-07-02 06:41:16.575 yield ' ' + aelt
2025-07-02 06:41:16.575
2025-07-02 06:41:16.575 # pump out diffs from after the synch point
2025-07-02 06:41:16.575 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.575
2025-07-02 06:41:16.575 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.575 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.575
2025-07-02 06:41:16.575 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.575 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.575 alo = 81, ahi = 1101
2025-07-02 06:41:16.575 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.575 blo = 81, bhi = 1101
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.576 g = []
2025-07-02 06:41:16.576 if alo < ahi:
2025-07-02 06:41:16.576 if blo < bhi:
2025-07-02 06:41:16.576 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.576 else:
2025-07-02 06:41:16.576 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.576 elif blo < bhi:
2025-07-02 06:41:16.576 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 > yield from g
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.576 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.576 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.576 alo = 81, ahi = 1101
2025-07-02 06:41:16.576 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.577 blo = 81, bhi = 1101
2025-07-02 06:41:16.577
2025-07-02 06:41:16.577 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.577 r"""
2025-07-02 06:41:16.577 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.577 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.577 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.577 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.577
2025-07-02 06:41:16.577 Example:
2025-07-02 06:41:16.577
2025-07-02 06:41:16.577 >>> d = Differ()
2025-07-02 06:41:16.577 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.577 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.577 >>> print(''.join(results), end="")
2025-07-02 06:41:16.577 - abcDefghiJkl
2025-07-02 06:41:16.577 + abcdefGhijkl
2025-07-02 06:41:16.577 """
2025-07-02 06:41:16.577
2025-07-02 06:41:16.578 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.578 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.578 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.578 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.578 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.578
2025-07-02 06:41:16.578 # search for the pair that matches best without being identical
2025-07-02 06:41:16.578 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.578 # on junk -- unless we have to)
2025-07-02 06:41:16.578 for j in range(blo, bhi):
2025-07-02 06:41:16.578 bj = b[j]
2025-07-02 06:41:16.578 cruncher.set_seq2(bj)
2025-07-02 06:41:16.578 for i in range(alo, ahi):
2025-07-02 06:41:16.578 ai = a[i]
2025-07-02 06:41:16.578 if ai == bj:
2025-07-02 06:41:16.578 if eqi is None:
2025-07-02 06:41:16.578 eqi, eqj = i, j
2025-07-02 06:41:16.578 continue
2025-07-02 06:41:16.578 cruncher.set_seq1(ai)
2025-07-02 06:41:16.578 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.579 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.579 # compares by a factor of 3.
2025-07-02 06:41:16.579 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.579 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.579 # of the computation is cached by cruncher
2025-07-02 06:41:16.579 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.579 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.579 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.579 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.579 if best_ratio < cutoff:
2025-07-02 06:41:16.579 # no non-identical "pretty close" pair
2025-07-02 06:41:16.579 if eqi is None:
2025-07-02 06:41:16.579 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.579 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.579 return
2025-07-02 06:41:16.579 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.579 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.579 else:
2025-07-02 06:41:16.579 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.579 eqi = None
2025-07-02 06:41:16.580
2025-07-02 06:41:16.580 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.580 # identical
2025-07-02 06:41:16.580
2025-07-02 06:41:16.580 # pump out diffs from before the synch point
2025-07-02 06:41:16.580 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.580
2025-07-02 06:41:16.580 # do intraline marking on the synch pair
2025-07-02 06:41:16.580 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.580 if eqi is None:
2025-07-02 06:41:16.580 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.580 atags = btags = ""
2025-07-02 06:41:16.580 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.580 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.580 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.580 if tag == 'replace':
2025-07-02 06:41:16.580 atags += '^' * la
2025-07-02 06:41:16.580 btags += '^' * lb
2025-07-02 06:41:16.580 elif tag == 'delete':
2025-07-02 06:41:16.580 atags += '-' * la
2025-07-02 06:41:16.580 elif tag == 'insert':
2025-07-02 06:41:16.581 btags += '+' * lb
2025-07-02 06:41:16.581 elif tag == 'equal':
2025-07-02 06:41:16.581 atags += ' ' * la
2025-07-02 06:41:16.581 btags += ' ' * lb
2025-07-02 06:41:16.581 else:
2025-07-02 06:41:16.581 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.581 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.581 else:
2025-07-02 06:41:16.581 # the synch pair is identical
2025-07-02 06:41:16.581 yield ' ' + aelt
2025-07-02 06:41:16.581
2025-07-02 06:41:16.581 # pump out diffs from after the synch point
2025-07-02 06:41:16.581 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.581
2025-07-02 06:41:16.581 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.581 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.581
2025-07-02 06:41:16.581 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.581 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.581 alo = 82, ahi = 1101
2025-07-02 06:41:16.582 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.582 blo = 82, bhi = 1101
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.582 g = []
2025-07-02 06:41:16.582 if alo < ahi:
2025-07-02 06:41:16.582 if blo < bhi:
2025-07-02 06:41:16.582 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.582 else:
2025-07-02 06:41:16.582 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.582 elif blo < bhi:
2025-07-02 06:41:16.582 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 > yield from g
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.582 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.583 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.583 alo = 82, ahi = 1101
2025-07-02 06:41:16.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.583 blo = 82, bhi = 1101
2025-07-02 06:41:16.583
2025-07-02 06:41:16.583 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.583 r"""
2025-07-02 06:41:16.583 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.583 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.583 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.583 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.583
2025-07-02 06:41:16.583 Example:
2025-07-02 06:41:16.583
2025-07-02 06:41:16.583 >>> d = Differ()
2025-07-02 06:41:16.583 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.583 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.583 >>> print(''.join(results), end="")
2025-07-02 06:41:16.583 - abcDefghiJkl
2025-07-02 06:41:16.584 + abcdefGhijkl
2025-07-02 06:41:16.584 """
2025-07-02 06:41:16.584
2025-07-02 06:41:16.584 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.584 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.584 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.584 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.584 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.584
2025-07-02 06:41:16.584 # search for the pair that matches best without being identical
2025-07-02 06:41:16.584 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.584 # on junk -- unless we have to)
2025-07-02 06:41:16.584 for j in range(blo, bhi):
2025-07-02 06:41:16.584 bj = b[j]
2025-07-02 06:41:16.584 cruncher.set_seq2(bj)
2025-07-02 06:41:16.584 for i in range(alo, ahi):
2025-07-02 06:41:16.584 ai = a[i]
2025-07-02 06:41:16.584 if ai == bj:
2025-07-02 06:41:16.585 if eqi is None:
2025-07-02 06:41:16.585 eqi, eqj = i, j
2025-07-02 06:41:16.585 continue
2025-07-02 06:41:16.585 cruncher.set_seq1(ai)
2025-07-02 06:41:16.585 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.585 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.585 # compares by a factor of 3.
2025-07-02 06:41:16.585 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.585 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.585 # of the computation is cached by cruncher
2025-07-02 06:41:16.585 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.585 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.585 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.585 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.585 if best_ratio < cutoff:
2025-07-02 06:41:16.585 # no non-identical "pretty close" pair
2025-07-02 06:41:16.585 if eqi is None:
2025-07-02 06:41:16.585 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.586 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.586 return
2025-07-02 06:41:16.586 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.586 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.586 else:
2025-07-02 06:41:16.586 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.586 eqi = None
2025-07-02 06:41:16.586
2025-07-02 06:41:16.586 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.586 # identical
2025-07-02 06:41:16.586
2025-07-02 06:41:16.586 # pump out diffs from before the synch point
2025-07-02 06:41:16.586 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.586
2025-07-02 06:41:16.586 # do intraline marking on the synch pair
2025-07-02 06:41:16.586 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.586 if eqi is None:
2025-07-02 06:41:16.586 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.586 atags = btags = ""
2025-07-02 06:41:16.586 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.587 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.587 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.587 if tag == 'replace':
2025-07-02 06:41:16.587 atags += '^' * la
2025-07-02 06:41:16.587 btags += '^' * lb
2025-07-02 06:41:16.587 elif tag == 'delete':
2025-07-02 06:41:16.587 atags += '-' * la
2025-07-02 06:41:16.587 elif tag == 'insert':
2025-07-02 06:41:16.587 btags += '+' * lb
2025-07-02 06:41:16.587 elif tag == 'equal':
2025-07-02 06:41:16.587 atags += ' ' * la
2025-07-02 06:41:16.587 btags += ' ' * lb
2025-07-02 06:41:16.587 else:
2025-07-02 06:41:16.587 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.587 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.587 else:
2025-07-02 06:41:16.587 # the synch pair is identical
2025-07-02 06:41:16.587 yield ' ' + aelt
2025-07-02 06:41:16.587
2025-07-02 06:41:16.587 # pump out diffs from after the synch point
2025-07-02 06:41:16.588 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.588
2025-07-02 06:41:16.588 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.588 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.588
2025-07-02 06:41:16.588 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.588 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.588 alo = 83, ahi = 1101
2025-07-02 06:41:16.588 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.588 blo = 83, bhi = 1101
2025-07-02 06:41:16.588
2025-07-02 06:41:16.588 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.588 g = []
2025-07-02 06:41:16.588 if alo < ahi:
2025-07-02 06:41:16.588 if blo < bhi:
2025-07-02 06:41:16.588 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.588 else:
2025-07-02 06:41:16.588 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.588 elif blo < bhi:
2025-07-02 06:41:16.588 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 > yield from g
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.589 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.589 alo = 83, ahi = 1101
2025-07-02 06:41:16.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.589 blo = 83, bhi = 1101
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.589 r"""
2025-07-02 06:41:16.589 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.589 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.589 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.589 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 Example:
2025-07-02 06:41:16.590
2025-07-02 06:41:16.590 >>> d = Differ()
2025-07-02 06:41:16.590 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.590 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.590 >>> print(''.join(results), end="")
2025-07-02 06:41:16.590 - abcDefghiJkl
2025-07-02 06:41:16.590 + abcdefGhijkl
2025-07-02 06:41:16.590 """
2025-07-02 06:41:16.590
2025-07-02 06:41:16.590 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.590 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.590 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.590 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.590 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.590
2025-07-02 06:41:16.590 # search for the pair that matches best without being identical
2025-07-02 06:41:16.591 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.591 # on junk -- unless we have to)
2025-07-02 06:41:16.591 for j in range(blo, bhi):
2025-07-02 06:41:16.591 bj = b[j]
2025-07-02 06:41:16.591 cruncher.set_seq2(bj)
2025-07-02 06:41:16.591 for i in range(alo, ahi):
2025-07-02 06:41:16.591 ai = a[i]
2025-07-02 06:41:16.591 if ai == bj:
2025-07-02 06:41:16.591 if eqi is None:
2025-07-02 06:41:16.591 eqi, eqj = i, j
2025-07-02 06:41:16.591 continue
2025-07-02 06:41:16.591 cruncher.set_seq1(ai)
2025-07-02 06:41:16.591 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.591 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.591 # compares by a factor of 3.
2025-07-02 06:41:16.591 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.591 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.591 # of the computation is cached by cruncher
2025-07-02 06:41:16.591 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.592 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.592 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.592 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.592 if best_ratio < cutoff:
2025-07-02 06:41:16.592 # no non-identical "pretty close" pair
2025-07-02 06:41:16.592 if eqi is None:
2025-07-02 06:41:16.592 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.592 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.592 return
2025-07-02 06:41:16.592 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.592 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.592 else:
2025-07-02 06:41:16.592 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.592 eqi = None
2025-07-02 06:41:16.592
2025-07-02 06:41:16.592 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.592 # identical
2025-07-02 06:41:16.592
2025-07-02 06:41:16.592 # pump out diffs from before the synch point
2025-07-02 06:41:16.592 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.593
2025-07-02 06:41:16.593 # do intraline marking on the synch pair
2025-07-02 06:41:16.593 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.593 if eqi is None:
2025-07-02 06:41:16.593 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.593 atags = btags = ""
2025-07-02 06:41:16.593 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.593 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.593 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.593 if tag == 'replace':
2025-07-02 06:41:16.593 atags += '^' * la
2025-07-02 06:41:16.593 btags += '^' * lb
2025-07-02 06:41:16.593 elif tag == 'delete':
2025-07-02 06:41:16.593 atags += '-' * la
2025-07-02 06:41:16.593 elif tag == 'insert':
2025-07-02 06:41:16.593 btags += '+' * lb
2025-07-02 06:41:16.593 elif tag == 'equal':
2025-07-02 06:41:16.593 atags += ' ' * la
2025-07-02 06:41:16.593 btags += ' ' * lb
2025-07-02 06:41:16.593 else:
2025-07-02 06:41:16.594 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.594 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.594 else:
2025-07-02 06:41:16.594 # the synch pair is identical
2025-07-02 06:41:16.594 yield ' ' + aelt
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594 # pump out diffs from after the synch point
2025-07-02 06:41:16.594 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.594 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.594 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.594 alo = 84, ahi = 1101
2025-07-02 06:41:16.594 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.594 blo = 84, bhi = 1101
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.594 g = []
2025-07-02 06:41:16.594 if alo < ahi:
2025-07-02 06:41:16.595 if blo < bhi:
2025-07-02 06:41:16.595 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.595 else:
2025-07-02 06:41:16.595 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.595 elif blo < bhi:
2025-07-02 06:41:16.595 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 > yield from g
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.595 alo = 84, ahi = 1101
2025-07-02 06:41:16.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.595 blo = 84, bhi = 1101
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.595 r"""
2025-07-02 06:41:16.596 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.596 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.596 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.596 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.596
2025-07-02 06:41:16.596 Example:
2025-07-02 06:41:16.596
2025-07-02 06:41:16.596 >>> d = Differ()
2025-07-02 06:41:16.596 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.596 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.596 >>> print(''.join(results), end="")
2025-07-02 06:41:16.596 - abcDefghiJkl
2025-07-02 06:41:16.596 + abcdefGhijkl
2025-07-02 06:41:16.596 """
2025-07-02 06:41:16.596
2025-07-02 06:41:16.596 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.596 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.596 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.597 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.597 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.597
2025-07-02 06:41:16.597 # search for the pair that matches best without being identical
2025-07-02 06:41:16.597 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.597 # on junk -- unless we have to)
2025-07-02 06:41:16.597 for j in range(blo, bhi):
2025-07-02 06:41:16.597 bj = b[j]
2025-07-02 06:41:16.597 cruncher.set_seq2(bj)
2025-07-02 06:41:16.597 for i in range(alo, ahi):
2025-07-02 06:41:16.597 ai = a[i]
2025-07-02 06:41:16.597 if ai == bj:
2025-07-02 06:41:16.597 if eqi is None:
2025-07-02 06:41:16.597 eqi, eqj = i, j
2025-07-02 06:41:16.597 continue
2025-07-02 06:41:16.597 cruncher.set_seq1(ai)
2025-07-02 06:41:16.597 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.597 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.597 # compares by a factor of 3.
2025-07-02 06:41:16.597 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.597 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.598 # of the computation is cached by cruncher
2025-07-02 06:41:16.598 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.598 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.598 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.598 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.598 if best_ratio < cutoff:
2025-07-02 06:41:16.598 # no non-identical "pretty close" pair
2025-07-02 06:41:16.598 if eqi is None:
2025-07-02 06:41:16.598 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.598 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.598 return
2025-07-02 06:41:16.598 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.598 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.598 else:
2025-07-02 06:41:16.598 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.598 eqi = None
2025-07-02 06:41:16.598
2025-07-02 06:41:16.598 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.598 # identical
2025-07-02 06:41:16.598
2025-07-02 06:41:16.599 # pump out diffs from before the synch point
2025-07-02 06:41:16.599 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.599
2025-07-02 06:41:16.599 # do intraline marking on the synch pair
2025-07-02 06:41:16.599 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.599 if eqi is None:
2025-07-02 06:41:16.599 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.599 atags = btags = ""
2025-07-02 06:41:16.599 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.599 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.599 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.599 if tag == 'replace':
2025-07-02 06:41:16.599 atags += '^' * la
2025-07-02 06:41:16.599 btags += '^' * lb
2025-07-02 06:41:16.599 elif tag == 'delete':
2025-07-02 06:41:16.599 atags += '-' * la
2025-07-02 06:41:16.599 elif tag == 'insert':
2025-07-02 06:41:16.599 btags += '+' * lb
2025-07-02 06:41:16.600 elif tag == 'equal':
2025-07-02 06:41:16.600 atags += ' ' * la
2025-07-02 06:41:16.600 btags += ' ' * lb
2025-07-02 06:41:16.600 else:
2025-07-02 06:41:16.600 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.600 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.600 else:
2025-07-02 06:41:16.600 # the synch pair is identical
2025-07-02 06:41:16.600 yield ' ' + aelt
2025-07-02 06:41:16.600
2025-07-02 06:41:16.600 # pump out diffs from after the synch point
2025-07-02 06:41:16.600 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.600
2025-07-02 06:41:16.600 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.600 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.600
2025-07-02 06:41:16.600 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.600 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.600 alo = 85, ahi = 1101
2025-07-02 06:41:16.600 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.601 blo = 85, bhi = 1101
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.601 g = []
2025-07-02 06:41:16.601 if alo < ahi:
2025-07-02 06:41:16.601 if blo < bhi:
2025-07-02 06:41:16.601 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.601 else:
2025-07-02 06:41:16.601 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.601 elif blo < bhi:
2025-07-02 06:41:16.601 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 > yield from g
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.601 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.602 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.602 alo = 85, ahi = 1101
2025-07-02 06:41:16.602 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.602 blo = 85, bhi = 1101
2025-07-02 06:41:16.602
2025-07-02 06:41:16.602 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.602 r"""
2025-07-02 06:41:16.602 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.602 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.602 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.602 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.602
2025-07-02 06:41:16.602 Example:
2025-07-02 06:41:16.602
2025-07-02 06:41:16.602 >>> d = Differ()
2025-07-02 06:41:16.602 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.602 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.602 >>> print(''.join(results), end="")
2025-07-02 06:41:16.602 - abcDefghiJkl
2025-07-02 06:41:16.603 + abcdefGhijkl
2025-07-02 06:41:16.603 """
2025-07-02 06:41:16.603
2025-07-02 06:41:16.603 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.603 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.603 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.603 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.603 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.603
2025-07-02 06:41:16.603 # search for the pair that matches best without being identical
2025-07-02 06:41:16.603 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.603 # on junk -- unless we have to)
2025-07-02 06:41:16.603 for j in range(blo, bhi):
2025-07-02 06:41:16.603 bj = b[j]
2025-07-02 06:41:16.603 cruncher.set_seq2(bj)
2025-07-02 06:41:16.603 for i in range(alo, ahi):
2025-07-02 06:41:16.603 ai = a[i]
2025-07-02 06:41:16.603 if ai == bj:
2025-07-02 06:41:16.603 if eqi is None:
2025-07-02 06:41:16.604 eqi, eqj = i, j
2025-07-02 06:41:16.604 continue
2025-07-02 06:41:16.604 cruncher.set_seq1(ai)
2025-07-02 06:41:16.604 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.604 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.604 # compares by a factor of 3.
2025-07-02 06:41:16.604 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.604 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.604 # of the computation is cached by cruncher
2025-07-02 06:41:16.604 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.604 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.604 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.604 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.604 if best_ratio < cutoff:
2025-07-02 06:41:16.604 # no non-identical "pretty close" pair
2025-07-02 06:41:16.604 if eqi is None:
2025-07-02 06:41:16.604 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.604 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.604 return
2025-07-02 06:41:16.604 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.604 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.605 else:
2025-07-02 06:41:16.605 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.605 eqi = None
2025-07-02 06:41:16.605
2025-07-02 06:41:16.605 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.605 # identical
2025-07-02 06:41:16.605
2025-07-02 06:41:16.605 # pump out diffs from before the synch point
2025-07-02 06:41:16.605 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.605
2025-07-02 06:41:16.605 # do intraline marking on the synch pair
2025-07-02 06:41:16.605 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.605 if eqi is None:
2025-07-02 06:41:16.605 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.605 atags = btags = ""
2025-07-02 06:41:16.605 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.605 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.605 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.605 if tag == 'replace':
2025-07-02 06:41:16.605 atags += '^' * la
2025-07-02 06:41:16.606 btags += '^' * lb
2025-07-02 06:41:16.606 elif tag == 'delete':
2025-07-02 06:41:16.606 atags += '-' * la
2025-07-02 06:41:16.606 elif tag == 'insert':
2025-07-02 06:41:16.606 btags += '+' * lb
2025-07-02 06:41:16.606 elif tag == 'equal':
2025-07-02 06:41:16.606 atags += ' ' * la
2025-07-02 06:41:16.606 btags += ' ' * lb
2025-07-02 06:41:16.606 else:
2025-07-02 06:41:16.606 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.606 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.606 else:
2025-07-02 06:41:16.606 # the synch pair is identical
2025-07-02 06:41:16.606 yield ' ' + aelt
2025-07-02 06:41:16.606
2025-07-02 06:41:16.606 # pump out diffs from after the synch point
2025-07-02 06:41:16.606 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.606
2025-07-02 06:41:16.606 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.606 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.607 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.607 alo = 86, ahi = 1101
2025-07-02 06:41:16.607 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.607 blo = 86, bhi = 1101
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.607 g = []
2025-07-02 06:41:16.607 if alo < ahi:
2025-07-02 06:41:16.607 if blo < bhi:
2025-07-02 06:41:16.607 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.607 else:
2025-07-02 06:41:16.607 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.607 elif blo < bhi:
2025-07-02 06:41:16.607 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 > yield from g
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.607 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.608 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.608 alo = 86, ahi = 1101
2025-07-02 06:41:16.608 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.608 blo = 86, bhi = 1101
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.608 r"""
2025-07-02 06:41:16.608 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.608 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.608 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.608 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608 Example:
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608 >>> d = Differ()
2025-07-02 06:41:16.608 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.609 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.609 >>> print(''.join(results), end="")
2025-07-02 06:41:16.609 - abcDefghiJkl
2025-07-02 06:41:16.609 + abcdefGhijkl
2025-07-02 06:41:16.609 """
2025-07-02 06:41:16.609
2025-07-02 06:41:16.609 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.609 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.609 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.609 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.609 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.609
2025-07-02 06:41:16.609 # search for the pair that matches best without being identical
2025-07-02 06:41:16.609 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.609 # on junk -- unless we have to)
2025-07-02 06:41:16.609 for j in range(blo, bhi):
2025-07-02 06:41:16.609 bj = b[j]
2025-07-02 06:41:16.609 cruncher.set_seq2(bj)
2025-07-02 06:41:16.610 for i in range(alo, ahi):
2025-07-02 06:41:16.610 ai = a[i]
2025-07-02 06:41:16.610 if ai == bj:
2025-07-02 06:41:16.610 if eqi is None:
2025-07-02 06:41:16.610 eqi, eqj = i, j
2025-07-02 06:41:16.610 continue
2025-07-02 06:41:16.610 cruncher.set_seq1(ai)
2025-07-02 06:41:16.610 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.610 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.610 # compares by a factor of 3.
2025-07-02 06:41:16.610 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.610 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.610 # of the computation is cached by cruncher
2025-07-02 06:41:16.610 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.610 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.610 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.610 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.610 if best_ratio < cutoff:
2025-07-02 06:41:16.610 # no non-identical "pretty close" pair
2025-07-02 06:41:16.610 if eqi is None:
2025-07-02 06:41:16.611 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.611 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.611 return
2025-07-02 06:41:16.611 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.611 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.611 else:
2025-07-02 06:41:16.611 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.611 eqi = None
2025-07-02 06:41:16.611
2025-07-02 06:41:16.611 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.611 # identical
2025-07-02 06:41:16.611
2025-07-02 06:41:16.611 # pump out diffs from before the synch point
2025-07-02 06:41:16.611 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.611
2025-07-02 06:41:16.611 # do intraline marking on the synch pair
2025-07-02 06:41:16.611 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.611 if eqi is None:
2025-07-02 06:41:16.611 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.611 atags = btags = ""
2025-07-02 06:41:16.612 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.612 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.612 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.612 if tag == 'replace':
2025-07-02 06:41:16.612 atags += '^' * la
2025-07-02 06:41:16.612 btags += '^' * lb
2025-07-02 06:41:16.612 elif tag == 'delete':
2025-07-02 06:41:16.612 atags += '-' * la
2025-07-02 06:41:16.612 elif tag == 'insert':
2025-07-02 06:41:16.612 btags += '+' * lb
2025-07-02 06:41:16.612 elif tag == 'equal':
2025-07-02 06:41:16.612 atags += ' ' * la
2025-07-02 06:41:16.612 btags += ' ' * lb
2025-07-02 06:41:16.612 else:
2025-07-02 06:41:16.612 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.612 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.612 else:
2025-07-02 06:41:16.612 # the synch pair is identical
2025-07-02 06:41:16.612 yield ' ' + aelt
2025-07-02 06:41:16.612
2025-07-02 06:41:16.613 # pump out diffs from after the synch point
2025-07-02 06:41:16.613 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.613
2025-07-02 06:41:16.613 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.613 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.613
2025-07-02 06:41:16.613 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.613 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.613 alo = 87, ahi = 1101
2025-07-02 06:41:16.613 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.613 blo = 87, bhi = 1101
2025-07-02 06:41:16.613
2025-07-02 06:41:16.613 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.613 g = []
2025-07-02 06:41:16.613 if alo < ahi:
2025-07-02 06:41:16.613 if blo < bhi:
2025-07-02 06:41:16.613 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.613 else:
2025-07-02 06:41:16.613 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.613 elif blo < bhi:
2025-07-02 06:41:16.614 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 > yield from g
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.614 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.614 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.614 alo = 87, ahi = 1101
2025-07-02 06:41:16.614 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.614 blo = 87, bhi = 1101
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.614 r"""
2025-07-02 06:41:16.614 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.614 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.614 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.614 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 Example:
2025-07-02 06:41:16.615
2025-07-02 06:41:16.615 >>> d = Differ()
2025-07-02 06:41:16.615 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.615 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.615 >>> print(''.join(results), end="")
2025-07-02 06:41:16.615 - abcDefghiJkl
2025-07-02 06:41:16.615 + abcdefGhijkl
2025-07-02 06:41:16.615 """
2025-07-02 06:41:16.615
2025-07-02 06:41:16.615 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.615 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.615 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.615 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.615 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.615
2025-07-02 06:41:16.615 # search for the pair that matches best without being identical
2025-07-02 06:41:16.615 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.615 # on junk -- unless we have to)
2025-07-02 06:41:16.616 for j in range(blo, bhi):
2025-07-02 06:41:16.616 bj = b[j]
2025-07-02 06:41:16.616 cruncher.set_seq2(bj)
2025-07-02 06:41:16.616 for i in range(alo, ahi):
2025-07-02 06:41:16.616 ai = a[i]
2025-07-02 06:41:16.616 if ai == bj:
2025-07-02 06:41:16.616 if eqi is None:
2025-07-02 06:41:16.616 eqi, eqj = i, j
2025-07-02 06:41:16.616 continue
2025-07-02 06:41:16.616 cruncher.set_seq1(ai)
2025-07-02 06:41:16.616 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.616 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.616 # compares by a factor of 3.
2025-07-02 06:41:16.616 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.616 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.616 # of the computation is cached by cruncher
2025-07-02 06:41:16.616 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.616 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.616 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.617 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.617 if best_ratio < cutoff:
2025-07-02 06:41:16.617 # no non-identical "pretty close" pair
2025-07-02 06:41:16.617 if eqi is None:
2025-07-02 06:41:16.617 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.617 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.617 return
2025-07-02 06:41:16.617 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.617 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.617 else:
2025-07-02 06:41:16.617 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.617 eqi = None
2025-07-02 06:41:16.617
2025-07-02 06:41:16.617 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.617 # identical
2025-07-02 06:41:16.617
2025-07-02 06:41:16.617 # pump out diffs from before the synch point
2025-07-02 06:41:16.617 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.617
2025-07-02 06:41:16.618 # do intraline marking on the synch pair
2025-07-02 06:41:16.618 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.618 if eqi is None:
2025-07-02 06:41:16.618 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.618 atags = btags = ""
2025-07-02 06:41:16.618 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.618 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.618 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.618 if tag == 'replace':
2025-07-02 06:41:16.618 atags += '^' * la
2025-07-02 06:41:16.618 btags += '^' * lb
2025-07-02 06:41:16.618 elif tag == 'delete':
2025-07-02 06:41:16.618 atags += '-' * la
2025-07-02 06:41:16.618 elif tag == 'insert':
2025-07-02 06:41:16.618 btags += '+' * lb
2025-07-02 06:41:16.618 elif tag == 'equal':
2025-07-02 06:41:16.618 atags += ' ' * la
2025-07-02 06:41:16.618 btags += ' ' * lb
2025-07-02 06:41:16.618 else:
2025-07-02 06:41:16.619 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.619 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.619 else:
2025-07-02 06:41:16.619 # the synch pair is identical
2025-07-02 06:41:16.619 yield ' ' + aelt
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619 # pump out diffs from after the synch point
2025-07-02 06:41:16.619 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.619 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.619 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.619 alo = 88, ahi = 1101
2025-07-02 06:41:16.619 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.619 blo = 88, bhi = 1101
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.619 g = []
2025-07-02 06:41:16.620 if alo < ahi:
2025-07-02 06:41:16.620 if blo < bhi:
2025-07-02 06:41:16.620 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.620 else:
2025-07-02 06:41:16.620 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.620 elif blo < bhi:
2025-07-02 06:41:16.620 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.620
2025-07-02 06:41:16.620 > yield from g
2025-07-02 06:41:16.620
2025-07-02 06:41:16.620 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.620 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.620
2025-07-02 06:41:16.620 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.620 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.620 alo = 88, ahi = 1101
2025-07-02 06:41:16.620 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.620 blo = 88, bhi = 1101
2025-07-02 06:41:16.620
2025-07-02 06:41:16.621 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.621 r"""
2025-07-02 06:41:16.621 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.621 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.621 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.621 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.621
2025-07-02 06:41:16.621 Example:
2025-07-02 06:41:16.621
2025-07-02 06:41:16.621 >>> d = Differ()
2025-07-02 06:41:16.621 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.621 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.621 >>> print(''.join(results), end="")
2025-07-02 06:41:16.621 - abcDefghiJkl
2025-07-02 06:41:16.621 + abcdefGhijkl
2025-07-02 06:41:16.621 """
2025-07-02 06:41:16.621
2025-07-02 06:41:16.621 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.622 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.622 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.622 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.622 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.622
2025-07-02 06:41:16.622 # search for the pair that matches best without being identical
2025-07-02 06:41:16.622 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.622 # on junk -- unless we have to)
2025-07-02 06:41:16.622 for j in range(blo, bhi):
2025-07-02 06:41:16.622 bj = b[j]
2025-07-02 06:41:16.622 cruncher.set_seq2(bj)
2025-07-02 06:41:16.622 for i in range(alo, ahi):
2025-07-02 06:41:16.622 ai = a[i]
2025-07-02 06:41:16.622 if ai == bj:
2025-07-02 06:41:16.622 if eqi is None:
2025-07-02 06:41:16.622 eqi, eqj = i, j
2025-07-02 06:41:16.622 continue
2025-07-02 06:41:16.622 cruncher.set_seq1(ai)
2025-07-02 06:41:16.622 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.622 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.623 # compares by a factor of 3.
2025-07-02 06:41:16.623 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.623 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.623 # of the computation is cached by cruncher
2025-07-02 06:41:16.623 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.623 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.623 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.623 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.623 if best_ratio < cutoff:
2025-07-02 06:41:16.623 # no non-identical "pretty close" pair
2025-07-02 06:41:16.623 if eqi is None:
2025-07-02 06:41:16.623 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.623 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.623 return
2025-07-02 06:41:16.623 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.623 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.623 else:
2025-07-02 06:41:16.623 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.623 eqi = None
2025-07-02 06:41:16.623
2025-07-02 06:41:16.624 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.624 # identical
2025-07-02 06:41:16.624
2025-07-02 06:41:16.624 # pump out diffs from before the synch point
2025-07-02 06:41:16.624 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.624
2025-07-02 06:41:16.624 # do intraline marking on the synch pair
2025-07-02 06:41:16.624 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.624 if eqi is None:
2025-07-02 06:41:16.624 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.624 atags = btags = ""
2025-07-02 06:41:16.624 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.624 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.624 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.624 if tag == 'replace':
2025-07-02 06:41:16.624 atags += '^' * la
2025-07-02 06:41:16.624 btags += '^' * lb
2025-07-02 06:41:16.624 elif tag == 'delete':
2025-07-02 06:41:16.624 atags += '-' * la
2025-07-02 06:41:16.625 elif tag == 'insert':
2025-07-02 06:41:16.625 btags += '+' * lb
2025-07-02 06:41:16.625 elif tag == 'equal':
2025-07-02 06:41:16.625 atags += ' ' * la
2025-07-02 06:41:16.625 btags += ' ' * lb
2025-07-02 06:41:16.625 else:
2025-07-02 06:41:16.625 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.625 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.625 else:
2025-07-02 06:41:16.625 # the synch pair is identical
2025-07-02 06:41:16.625 yield ' ' + aelt
2025-07-02 06:41:16.625
2025-07-02 06:41:16.625 # pump out diffs from after the synch point
2025-07-02 06:41:16.625 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.625
2025-07-02 06:41:16.625 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.625 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.625
2025-07-02 06:41:16.625 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.626 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.626 alo = 89, ahi = 1101
2025-07-02 06:41:16.626 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.626 blo = 89, bhi = 1101
2025-07-02 06:41:16.626
2025-07-02 06:41:16.626 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.626 g = []
2025-07-02 06:41:16.626 if alo < ahi:
2025-07-02 06:41:16.626 if blo < bhi:
2025-07-02 06:41:16.626 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.626 else:
2025-07-02 06:41:16.626 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.626 elif blo < bhi:
2025-07-02 06:41:16.626 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.626
2025-07-02 06:41:16.626 > yield from g
2025-07-02 06:41:16.626
2025-07-02 06:41:16.626 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.627 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.627 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.627 alo = 89, ahi = 1101
2025-07-02 06:41:16.627 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.627 blo = 89, bhi = 1101
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.627 r"""
2025-07-02 06:41:16.627 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.627 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.627 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.627 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627 Example:
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627 >>> d = Differ()
2025-07-02 06:41:16.627 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.628 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.628 >>> print(''.join(results), end="")
2025-07-02 06:41:16.628 - abcDefghiJkl
2025-07-02 06:41:16.628 + abcdefGhijkl
2025-07-02 06:41:16.628 """
2025-07-02 06:41:16.628
2025-07-02 06:41:16.628 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.628 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.628 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.628 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.628 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.628
2025-07-02 06:41:16.628 # search for the pair that matches best without being identical
2025-07-02 06:41:16.628 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.628 # on junk -- unless we have to)
2025-07-02 06:41:16.628 for j in range(blo, bhi):
2025-07-02 06:41:16.628 bj = b[j]
2025-07-02 06:41:16.629 cruncher.set_seq2(bj)
2025-07-02 06:41:16.629 for i in range(alo, ahi):
2025-07-02 06:41:16.629 ai = a[i]
2025-07-02 06:41:16.629 if ai == bj:
2025-07-02 06:41:16.629 if eqi is None:
2025-07-02 06:41:16.629 eqi, eqj = i, j
2025-07-02 06:41:16.629 continue
2025-07-02 06:41:16.629 cruncher.set_seq1(ai)
2025-07-02 06:41:16.629 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.629 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.629 # compares by a factor of 3.
2025-07-02 06:41:16.629 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.629 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.629 # of the computation is cached by cruncher
2025-07-02 06:41:16.629 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.629 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.629 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.629 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.629 if best_ratio < cutoff:
2025-07-02 06:41:16.630 # no non-identical "pretty close" pair
2025-07-02 06:41:16.630 if eqi is None:
2025-07-02 06:41:16.630 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.630 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.630 return
2025-07-02 06:41:16.630 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.630 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.630 else:
2025-07-02 06:41:16.630 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.630 eqi = None
2025-07-02 06:41:16.630
2025-07-02 06:41:16.630 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.630 # identical
2025-07-02 06:41:16.630
2025-07-02 06:41:16.630 # pump out diffs from before the synch point
2025-07-02 06:41:16.630 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.630
2025-07-02 06:41:16.630 # do intraline marking on the synch pair
2025-07-02 06:41:16.630 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.630 if eqi is None:
2025-07-02 06:41:16.631 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.631 atags = btags = ""
2025-07-02 06:41:16.631 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.631 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.631 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.631 if tag == 'replace':
2025-07-02 06:41:16.631 atags += '^' * la
2025-07-02 06:41:16.631 btags += '^' * lb
2025-07-02 06:41:16.631 elif tag == 'delete':
2025-07-02 06:41:16.631 atags += '-' * la
2025-07-02 06:41:16.631 elif tag == 'insert':
2025-07-02 06:41:16.631 btags += '+' * lb
2025-07-02 06:41:16.631 elif tag == 'equal':
2025-07-02 06:41:16.631 atags += ' ' * la
2025-07-02 06:41:16.631 btags += ' ' * lb
2025-07-02 06:41:16.631 else:
2025-07-02 06:41:16.631 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.631 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.631 else:
2025-07-02 06:41:16.631 # the synch pair is identical
2025-07-02 06:41:16.632 yield ' ' + aelt
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632 # pump out diffs from after the synch point
2025-07-02 06:41:16.632 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.632 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.632 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.632 alo = 92, ahi = 1101
2025-07-02 06:41:16.632 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.632 blo = 92, bhi = 1101
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.632 g = []
2025-07-02 06:41:16.632 if alo < ahi:
2025-07-02 06:41:16.632 if blo < bhi:
2025-07-02 06:41:16.632 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.633 else:
2025-07-02 06:41:16.633 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.633 elif blo < bhi:
2025-07-02 06:41:16.633 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 > yield from g
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.633 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.633 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.633 alo = 92, ahi = 1101
2025-07-02 06:41:16.633 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.633 blo = 92, bhi = 1101
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.633 r"""
2025-07-02 06:41:16.634 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.634 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.634 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.634 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.634
2025-07-02 06:41:16.634 Example:
2025-07-02 06:41:16.634
2025-07-02 06:41:16.634 >>> d = Differ()
2025-07-02 06:41:16.634 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.634 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.634 >>> print(''.join(results), end="")
2025-07-02 06:41:16.634 - abcDefghiJkl
2025-07-02 06:41:16.634 + abcdefGhijkl
2025-07-02 06:41:16.634 """
2025-07-02 06:41:16.634
2025-07-02 06:41:16.634 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.634 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.635 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.635 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.635 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.635
2025-07-02 06:41:16.635 # search for the pair that matches best without being identical
2025-07-02 06:41:16.635 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.635 # on junk -- unless we have to)
2025-07-02 06:41:16.635 for j in range(blo, bhi):
2025-07-02 06:41:16.635 bj = b[j]
2025-07-02 06:41:16.635 cruncher.set_seq2(bj)
2025-07-02 06:41:16.635 for i in range(alo, ahi):
2025-07-02 06:41:16.635 ai = a[i]
2025-07-02 06:41:16.635 if ai == bj:
2025-07-02 06:41:16.635 if eqi is None:
2025-07-02 06:41:16.635 eqi, eqj = i, j
2025-07-02 06:41:16.635 continue
2025-07-02 06:41:16.635 cruncher.set_seq1(ai)
2025-07-02 06:41:16.635 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.635 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.636 # compares by a factor of 3.
2025-07-02 06:41:16.636 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.636 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.636 # of the computation is cached by cruncher
2025-07-02 06:41:16.636 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.636 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.636 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.636 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.636 if best_ratio < cutoff:
2025-07-02 06:41:16.636 # no non-identical "pretty close" pair
2025-07-02 06:41:16.636 if eqi is None:
2025-07-02 06:41:16.636 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.636 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.636 return
2025-07-02 06:41:16.636 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.636 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.636 else:
2025-07-02 06:41:16.636 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.636 eqi = None
2025-07-02 06:41:16.637
2025-07-02 06:41:16.637 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.637 # identical
2025-07-02 06:41:16.637
2025-07-02 06:41:16.637 # pump out diffs from before the synch point
2025-07-02 06:41:16.637 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.637
2025-07-02 06:41:16.637 # do intraline marking on the synch pair
2025-07-02 06:41:16.637 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.637 if eqi is None:
2025-07-02 06:41:16.637 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.637 atags = btags = ""
2025-07-02 06:41:16.637 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.637 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.637 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.637 if tag == 'replace':
2025-07-02 06:41:16.637 atags += '^' * la
2025-07-02 06:41:16.637 btags += '^' * lb
2025-07-02 06:41:16.637 elif tag == 'delete':
2025-07-02 06:41:16.637 atags += '-' * la
2025-07-02 06:41:16.638 elif tag == 'insert':
2025-07-02 06:41:16.638 btags += '+' * lb
2025-07-02 06:41:16.638 elif tag == 'equal':
2025-07-02 06:41:16.638 atags += ' ' * la
2025-07-02 06:41:16.638 btags += ' ' * lb
2025-07-02 06:41:16.638 else:
2025-07-02 06:41:16.638 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.638 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.638 else:
2025-07-02 06:41:16.638 # the synch pair is identical
2025-07-02 06:41:16.638 yield ' ' + aelt
2025-07-02 06:41:16.638
2025-07-02 06:41:16.638 # pump out diffs from after the synch point
2025-07-02 06:41:16.638 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.638
2025-07-02 06:41:16.638 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.638 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.638
2025-07-02 06:41:16.638 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.638 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.639 alo = 93, ahi = 1101
2025-07-02 06:41:16.639 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.639 blo = 93, bhi = 1101
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.639 g = []
2025-07-02 06:41:16.639 if alo < ahi:
2025-07-02 06:41:16.639 if blo < bhi:
2025-07-02 06:41:16.639 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.639 else:
2025-07-02 06:41:16.639 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.639 elif blo < bhi:
2025-07-02 06:41:16.639 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 > yield from g
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.639 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.640 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.640 alo = 93, ahi = 1101
2025-07-02 06:41:16.640 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.640 blo = 93, bhi = 1101
2025-07-02 06:41:16.640
2025-07-02 06:41:16.640 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.640 r"""
2025-07-02 06:41:16.640 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.640 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.640 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.640 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.640
2025-07-02 06:41:16.640 Example:
2025-07-02 06:41:16.640
2025-07-02 06:41:16.640 >>> d = Differ()
2025-07-02 06:41:16.640 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.640 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.640 >>> print(''.join(results), end="")
2025-07-02 06:41:16.640 - abcDefghiJkl
2025-07-02 06:41:16.641 + abcdefGhijkl
2025-07-02 06:41:16.641 """
2025-07-02 06:41:16.641
2025-07-02 06:41:16.641 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.641 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.641 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.641 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.641 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.641
2025-07-02 06:41:16.641 # search for the pair that matches best without being identical
2025-07-02 06:41:16.641 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.641 # on junk -- unless we have to)
2025-07-02 06:41:16.641 for j in range(blo, bhi):
2025-07-02 06:41:16.641 bj = b[j]
2025-07-02 06:41:16.641 cruncher.set_seq2(bj)
2025-07-02 06:41:16.641 for i in range(alo, ahi):
2025-07-02 06:41:16.641 ai = a[i]
2025-07-02 06:41:16.641 if ai == bj:
2025-07-02 06:41:16.642 if eqi is None:
2025-07-02 06:41:16.642 eqi, eqj = i, j
2025-07-02 06:41:16.642 continue
2025-07-02 06:41:16.642 cruncher.set_seq1(ai)
2025-07-02 06:41:16.642 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.642 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.642 # compares by a factor of 3.
2025-07-02 06:41:16.642 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.642 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.642 # of the computation is cached by cruncher
2025-07-02 06:41:16.642 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.642 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.642 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.642 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.642 if best_ratio < cutoff:
2025-07-02 06:41:16.642 # no non-identical "pretty close" pair
2025-07-02 06:41:16.642 if eqi is None:
2025-07-02 06:41:16.642 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.642 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.643 return
2025-07-02 06:41:16.643 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.643 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.643 else:
2025-07-02 06:41:16.643 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.643 eqi = None
2025-07-02 06:41:16.643
2025-07-02 06:41:16.643 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.643 # identical
2025-07-02 06:41:16.643
2025-07-02 06:41:16.643 # pump out diffs from before the synch point
2025-07-02 06:41:16.643 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.643
2025-07-02 06:41:16.643 # do intraline marking on the synch pair
2025-07-02 06:41:16.643 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.643 if eqi is None:
2025-07-02 06:41:16.643 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.643 atags = btags = ""
2025-07-02 06:41:16.643 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.644 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.644 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.644 if tag == 'replace':
2025-07-02 06:41:16.644 atags += '^' * la
2025-07-02 06:41:16.644 btags += '^' * lb
2025-07-02 06:41:16.644 elif tag == 'delete':
2025-07-02 06:41:16.644 atags += '-' * la
2025-07-02 06:41:16.644 elif tag == 'insert':
2025-07-02 06:41:16.644 btags += '+' * lb
2025-07-02 06:41:16.644 elif tag == 'equal':
2025-07-02 06:41:16.644 atags += ' ' * la
2025-07-02 06:41:16.644 btags += ' ' * lb
2025-07-02 06:41:16.644 else:
2025-07-02 06:41:16.644 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.644 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.644 else:
2025-07-02 06:41:16.644 # the synch pair is identical
2025-07-02 06:41:16.644 yield ' ' + aelt
2025-07-02 06:41:16.644
2025-07-02 06:41:16.645 # pump out diffs from after the synch point
2025-07-02 06:41:16.645 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.645
2025-07-02 06:41:16.645 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.645 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.645
2025-07-02 06:41:16.645 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.645 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.645 alo = 94, ahi = 1101
2025-07-02 06:41:16.645 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.645 blo = 94, bhi = 1101
2025-07-02 06:41:16.645
2025-07-02 06:41:16.645 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.645 g = []
2025-07-02 06:41:16.645 if alo < ahi:
2025-07-02 06:41:16.645 if blo < bhi:
2025-07-02 06:41:16.645 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.645 else:
2025-07-02 06:41:16.645 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.645 elif blo < bhi:
2025-07-02 06:41:16.646 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 > yield from g
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.646 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.646 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.646 alo = 94, ahi = 1101
2025-07-02 06:41:16.646 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.646 blo = 94, bhi = 1101
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.646 r"""
2025-07-02 06:41:16.646 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.646 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.646 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.646 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 Example:
2025-07-02 06:41:16.647
2025-07-02 06:41:16.647 >>> d = Differ()
2025-07-02 06:41:16.647 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.647 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.647 >>> print(''.join(results), end="")
2025-07-02 06:41:16.647 - abcDefghiJkl
2025-07-02 06:41:16.647 + abcdefGhijkl
2025-07-02 06:41:16.647 """
2025-07-02 06:41:16.647
2025-07-02 06:41:16.647 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.647 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.647 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.647 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.647 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.647
2025-07-02 06:41:16.647 # search for the pair that matches best without being identical
2025-07-02 06:41:16.647 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.647 # on junk -- unless we have to)
2025-07-02 06:41:16.648 for j in range(blo, bhi):
2025-07-02 06:41:16.648 bj = b[j]
2025-07-02 06:41:16.648 cruncher.set_seq2(bj)
2025-07-02 06:41:16.648 for i in range(alo, ahi):
2025-07-02 06:41:16.648 ai = a[i]
2025-07-02 06:41:16.648 if ai == bj:
2025-07-02 06:41:16.648 if eqi is None:
2025-07-02 06:41:16.648 eqi, eqj = i, j
2025-07-02 06:41:16.648 continue
2025-07-02 06:41:16.648 cruncher.set_seq1(ai)
2025-07-02 06:41:16.648 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.648 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.648 # compares by a factor of 3.
2025-07-02 06:41:16.648 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.648 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.648 # of the computation is cached by cruncher
2025-07-02 06:41:16.648 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.648 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.648 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.648 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.648 if best_ratio < cutoff:
2025-07-02 06:41:16.649 # no non-identical "pretty close" pair
2025-07-02 06:41:16.649 if eqi is None:
2025-07-02 06:41:16.649 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.649 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.649 return
2025-07-02 06:41:16.649 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.649 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.649 else:
2025-07-02 06:41:16.649 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.649 eqi = None
2025-07-02 06:41:16.649
2025-07-02 06:41:16.649 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.649 # identical
2025-07-02 06:41:16.649
2025-07-02 06:41:16.649 # pump out diffs from before the synch point
2025-07-02 06:41:16.649 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.649
2025-07-02 06:41:16.650 # do intraline marking on the synch pair
2025-07-02 06:41:16.650 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.650 if eqi is None:
2025-07-02 06:41:16.650 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.650 atags = btags = ""
2025-07-02 06:41:16.650 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.650 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.650 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.650 if tag == 'replace':
2025-07-02 06:41:16.650 atags += '^' * la
2025-07-02 06:41:16.650 btags += '^' * lb
2025-07-02 06:41:16.650 elif tag == 'delete':
2025-07-02 06:41:16.650 atags += '-' * la
2025-07-02 06:41:16.650 elif tag == 'insert':
2025-07-02 06:41:16.650 btags += '+' * lb
2025-07-02 06:41:16.650 elif tag == 'equal':
2025-07-02 06:41:16.650 atags += ' ' * la
2025-07-02 06:41:16.650 btags += ' ' * lb
2025-07-02 06:41:16.650 else:
2025-07-02 06:41:16.651 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.651 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.651 else:
2025-07-02 06:41:16.651 # the synch pair is identical
2025-07-02 06:41:16.651 yield ' ' + aelt
2025-07-02 06:41:16.651
2025-07-02 06:41:16.651 # pump out diffs from after the synch point
2025-07-02 06:41:16.651 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.651
2025-07-02 06:41:16.651 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.651 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.651
2025-07-02 06:41:16.651 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.651 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.651 alo = 95, ahi = 1101
2025-07-02 06:41:16.651 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.652 blo = 95, bhi = 1101
2025-07-02 06:41:16.652
2025-07-02 06:41:16.652 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.652 g = []
2025-07-02 06:41:16.652 if alo < ahi:
2025-07-02 06:41:16.652 if blo < bhi:
2025-07-02 06:41:16.652 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.652 else:
2025-07-02 06:41:16.652 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.652 elif blo < bhi:
2025-07-02 06:41:16.652 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.652
2025-07-02 06:41:16.652 > yield from g
2025-07-02 06:41:16.652
2025-07-02 06:41:16.652 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.652 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.653 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.653 alo = 95, ahi = 1101
2025-07-02 06:41:16.653 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.653 blo = 95, bhi = 1101
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.653 r"""
2025-07-02 06:41:16.653 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.653 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.653 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.653 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653 Example:
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653 >>> d = Differ()
2025-07-02 06:41:16.654 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.654 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.654 >>> print(''.join(results), end="")
2025-07-02 06:41:16.654 - abcDefghiJkl
2025-07-02 06:41:16.654 + abcdefGhijkl
2025-07-02 06:41:16.654 """
2025-07-02 06:41:16.654
2025-07-02 06:41:16.654 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.654 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.654 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.654 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.654 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.654
2025-07-02 06:41:16.655 # search for the pair that matches best without being identical
2025-07-02 06:41:16.655 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.655 # on junk -- unless we have to)
2025-07-02 06:41:16.655 for j in range(blo, bhi):
2025-07-02 06:41:16.655 bj = b[j]
2025-07-02 06:41:16.655 cruncher.set_seq2(bj)
2025-07-02 06:41:16.655 for i in range(alo, ahi):
2025-07-02 06:41:16.655 ai = a[i]
2025-07-02 06:41:16.655 if ai == bj:
2025-07-02 06:41:16.655 if eqi is None:
2025-07-02 06:41:16.655 eqi, eqj = i, j
2025-07-02 06:41:16.655 continue
2025-07-02 06:41:16.655 cruncher.set_seq1(ai)
2025-07-02 06:41:16.655 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.655 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.655 # compares by a factor of 3.
2025-07-02 06:41:16.656 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.656 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.656 # of the computation is cached by cruncher
2025-07-02 06:41:16.656 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.656 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.656 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.656 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.656 if best_ratio < cutoff:
2025-07-02 06:41:16.656 # no non-identical "pretty close" pair
2025-07-02 06:41:16.656 if eqi is None:
2025-07-02 06:41:16.656 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.656 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.656 return
2025-07-02 06:41:16.656 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.656 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.656 else:
2025-07-02 06:41:16.657 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.657 eqi = None
2025-07-02 06:41:16.657
2025-07-02 06:41:16.657 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.657 # identical
2025-07-02 06:41:16.657
2025-07-02 06:41:16.657 # pump out diffs from before the synch point
2025-07-02 06:41:16.657 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.657
2025-07-02 06:41:16.657 # do intraline marking on the synch pair
2025-07-02 06:41:16.657 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.657 if eqi is None:
2025-07-02 06:41:16.657 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.657 atags = btags = ""
2025-07-02 06:41:16.657 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.657 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.658 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.658 if tag == 'replace':
2025-07-02 06:41:16.658 atags += '^' * la
2025-07-02 06:41:16.658 btags += '^' * lb
2025-07-02 06:41:16.658 elif tag == 'delete':
2025-07-02 06:41:16.658 atags += '-' * la
2025-07-02 06:41:16.658 elif tag == 'insert':
2025-07-02 06:41:16.658 btags += '+' * lb
2025-07-02 06:41:16.658 elif tag == 'equal':
2025-07-02 06:41:16.658 atags += ' ' * la
2025-07-02 06:41:16.658 btags += ' ' * lb
2025-07-02 06:41:16.658 else:
2025-07-02 06:41:16.658 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.658 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.658 else:
2025-07-02 06:41:16.658 # the synch pair is identical
2025-07-02 06:41:16.658 yield ' ' + aelt
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659 # pump out diffs from after the synch point
2025-07-02 06:41:16.659 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.659 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.659 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.659 alo = 96, ahi = 1101
2025-07-02 06:41:16.659 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.659 blo = 96, bhi = 1101
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.660 g = []
2025-07-02 06:41:16.660 if alo < ahi:
2025-07-02 06:41:16.660 if blo < bhi:
2025-07-02 06:41:16.660 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.660 else:
2025-07-02 06:41:16.660 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.660 elif blo < bhi:
2025-07-02 06:41:16.660 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.660
2025-07-02 06:41:16.660 > yield from g
2025-07-02 06:41:16.660
2025-07-02 06:41:16.660 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.660 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.660
2025-07-02 06:41:16.660 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.660 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.661 alo = 96, ahi = 1101
2025-07-02 06:41:16.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.661 blo = 96, bhi = 1101
2025-07-02 06:41:16.661
2025-07-02 06:41:16.661 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.661 r"""
2025-07-02 06:41:16.661 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.661 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.661 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.661 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.661
2025-07-02 06:41:16.661 Example:
2025-07-02 06:41:16.661
2025-07-02 06:41:16.661 >>> d = Differ()
2025-07-02 06:41:16.661 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.661 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.662 >>> print(''.join(results), end="")
2025-07-02 06:41:16.662 - abcDefghiJkl
2025-07-02 06:41:16.662 + abcdefGhijkl
2025-07-02 06:41:16.662 """
2025-07-02 06:41:16.662
2025-07-02 06:41:16.662 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.662 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.662 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.662 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.662 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.662
2025-07-02 06:41:16.662 # search for the pair that matches best without being identical
2025-07-02 06:41:16.662 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.662 # on junk -- unless we have to)
2025-07-02 06:41:16.663 for j in range(blo, bhi):
2025-07-02 06:41:16.663 bj = b[j]
2025-07-02 06:41:16.663 cruncher.set_seq2(bj)
2025-07-02 06:41:16.663 for i in range(alo, ahi):
2025-07-02 06:41:16.663 ai = a[i]
2025-07-02 06:41:16.663 if ai == bj:
2025-07-02 06:41:16.663 if eqi is None:
2025-07-02 06:41:16.663 eqi, eqj = i, j
2025-07-02 06:41:16.663 continue
2025-07-02 06:41:16.663 cruncher.set_seq1(ai)
2025-07-02 06:41:16.663 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.663 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.663 # compares by a factor of 3.
2025-07-02 06:41:16.663 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.663 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.663 # of the computation is cached by cruncher
2025-07-02 06:41:16.664 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.664 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.664 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.664 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.664 if best_ratio < cutoff:
2025-07-02 06:41:16.664 # no non-identical "pretty close" pair
2025-07-02 06:41:16.664 if eqi is None:
2025-07-02 06:41:16.664 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.664 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.664 return
2025-07-02 06:41:16.664 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.664 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.664 else:
2025-07-02 06:41:16.664 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.664 eqi = None
2025-07-02 06:41:16.665
2025-07-02 06:41:16.665 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.665 # identical
2025-07-02 06:41:16.665
2025-07-02 06:41:16.665 # pump out diffs from before the synch point
2025-07-02 06:41:16.665 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.665
2025-07-02 06:41:16.665 # do intraline marking on the synch pair
2025-07-02 06:41:16.665 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.665 if eqi is None:
2025-07-02 06:41:16.665 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.665 atags = btags = ""
2025-07-02 06:41:16.665 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.665 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.665 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.665 if tag == 'replace':
2025-07-02 06:41:16.666 atags += '^' * la
2025-07-02 06:41:16.666 btags += '^' * lb
2025-07-02 06:41:16.666 elif tag == 'delete':
2025-07-02 06:41:16.666 atags += '-' * la
2025-07-02 06:41:16.666 elif tag == 'insert':
2025-07-02 06:41:16.666 btags += '+' * lb
2025-07-02 06:41:16.666 elif tag == 'equal':
2025-07-02 06:41:16.666 atags += ' ' * la
2025-07-02 06:41:16.666 btags += ' ' * lb
2025-07-02 06:41:16.666 else:
2025-07-02 06:41:16.666 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.666 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.666 else:
2025-07-02 06:41:16.666 # the synch pair is identical
2025-07-02 06:41:16.666 yield ' ' + aelt
2025-07-02 06:41:16.666
2025-07-02 06:41:16.666 # pump out diffs from after the synch point
2025-07-02 06:41:16.667 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.667
2025-07-02 06:41:16.667 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.667
2025-07-02 06:41:16.667 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.667 alo = 97, ahi = 1101
2025-07-02 06:41:16.667 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.667 blo = 97, bhi = 1101
2025-07-02 06:41:16.667
2025-07-02 06:41:16.667 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.667 g = []
2025-07-02 06:41:16.667 if alo < ahi:
2025-07-02 06:41:16.668 if blo < bhi:
2025-07-02 06:41:16.668 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.668 else:
2025-07-02 06:41:16.668 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.668 elif blo < bhi:
2025-07-02 06:41:16.668 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.668
2025-07-02 06:41:16.668 > yield from g
2025-07-02 06:41:16.668
2025-07-02 06:41:16.668 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.668 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.668
2025-07-02 06:41:16.668 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.668 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.668 alo = 97, ahi = 1101
2025-07-02 06:41:16.668 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.669 blo = 97, bhi = 1101
2025-07-02 06:41:16.669
2025-07-02 06:41:16.669 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.669 r"""
2025-07-02 06:41:16.669 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.669 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.669 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.669 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.669
2025-07-02 06:41:16.669 Example:
2025-07-02 06:41:16.669
2025-07-02 06:41:16.669 >>> d = Differ()
2025-07-02 06:41:16.669 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.669 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.669 >>> print(''.join(results), end="")
2025-07-02 06:41:16.669 - abcDefghiJkl
2025-07-02 06:41:16.670 + abcdefGhijkl
2025-07-02 06:41:16.670 """
2025-07-02 06:41:16.670
2025-07-02 06:41:16.670 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.670 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.670 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.670 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.670 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.670
2025-07-02 06:41:16.670 # search for the pair that matches best without being identical
2025-07-02 06:41:16.670 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.670 # on junk -- unless we have to)
2025-07-02 06:41:16.670 for j in range(blo, bhi):
2025-07-02 06:41:16.670 bj = b[j]
2025-07-02 06:41:16.671 cruncher.set_seq2(bj)
2025-07-02 06:41:16.671 for i in range(alo, ahi):
2025-07-02 06:41:16.671 ai = a[i]
2025-07-02 06:41:16.671 if ai == bj:
2025-07-02 06:41:16.671 if eqi is None:
2025-07-02 06:41:16.671 eqi, eqj = i, j
2025-07-02 06:41:16.671 continue
2025-07-02 06:41:16.671 cruncher.set_seq1(ai)
2025-07-02 06:41:16.671 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.671 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.671 # compares by a factor of 3.
2025-07-02 06:41:16.671 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.671 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.671 # of the computation is cached by cruncher
2025-07-02 06:41:16.671 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.671 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.671 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.671 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.672 if best_ratio < cutoff:
2025-07-02 06:41:16.672 # no non-identical "pretty close" pair
2025-07-02 06:41:16.672 if eqi is None:
2025-07-02 06:41:16.672 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.672 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.672 return
2025-07-02 06:41:16.672 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.672 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.672 else:
2025-07-02 06:41:16.672 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.672 eqi = None
2025-07-02 06:41:16.672
2025-07-02 06:41:16.672 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.672 # identical
2025-07-02 06:41:16.672
2025-07-02 06:41:16.672 # pump out diffs from before the synch point
2025-07-02 06:41:16.672 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.672
2025-07-02 06:41:16.672 # do intraline marking on the synch pair
2025-07-02 06:41:16.673 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.673 if eqi is None:
2025-07-02 06:41:16.673 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.673 atags = btags = ""
2025-07-02 06:41:16.673 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.673 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.673 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.673 if tag == 'replace':
2025-07-02 06:41:16.673 atags += '^' * la
2025-07-02 06:41:16.673 btags += '^' * lb
2025-07-02 06:41:16.673 elif tag == 'delete':
2025-07-02 06:41:16.673 atags += '-' * la
2025-07-02 06:41:16.673 elif tag == 'insert':
2025-07-02 06:41:16.673 btags += '+' * lb
2025-07-02 06:41:16.673 elif tag == 'equal':
2025-07-02 06:41:16.673 atags += ' ' * la
2025-07-02 06:41:16.673 btags += ' ' * lb
2025-07-02 06:41:16.673 else:
2025-07-02 06:41:16.673 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.674 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.674 else:
2025-07-02 06:41:16.674 # the synch pair is identical
2025-07-02 06:41:16.674 yield ' ' + aelt
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674 # pump out diffs from after the synch point
2025-07-02 06:41:16.674 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.674 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.674 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.674 alo = 98, ahi = 1101
2025-07-02 06:41:16.674 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.674 blo = 98, bhi = 1101
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.675 g = []
2025-07-02 06:41:16.675 if alo < ahi:
2025-07-02 06:41:16.675 if blo < bhi:
2025-07-02 06:41:16.675 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.675 else:
2025-07-02 06:41:16.675 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.675 elif blo < bhi:
2025-07-02 06:41:16.675 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.675
2025-07-02 06:41:16.675 > yield from g
2025-07-02 06:41:16.675
2025-07-02 06:41:16.675 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.675 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.675
2025-07-02 06:41:16.675 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.675 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.675 alo = 98, ahi = 1101
2025-07-02 06:41:16.675 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.675 blo = 98, bhi = 1101
2025-07-02 06:41:16.675
2025-07-02 06:41:16.676 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.676 r"""
2025-07-02 06:41:16.676 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.676 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.676 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.676 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.676
2025-07-02 06:41:16.676 Example:
2025-07-02 06:41:16.676
2025-07-02 06:41:16.676 >>> d = Differ()
2025-07-02 06:41:16.676 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.676 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.676 >>> print(''.join(results), end="")
2025-07-02 06:41:16.676 - abcDefghiJkl
2025-07-02 06:41:16.676 + abcdefGhijkl
2025-07-02 06:41:16.676 """
2025-07-02 06:41:16.676
2025-07-02 06:41:16.677 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.677 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.677 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.677 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.677 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.677
2025-07-02 06:41:16.677 # search for the pair that matches best without being identical
2025-07-02 06:41:16.677 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.677 # on junk -- unless we have to)
2025-07-02 06:41:16.677 for j in range(blo, bhi):
2025-07-02 06:41:16.677 bj = b[j]
2025-07-02 06:41:16.677 cruncher.set_seq2(bj)
2025-07-02 06:41:16.677 for i in range(alo, ahi):
2025-07-02 06:41:16.677 ai = a[i]
2025-07-02 06:41:16.677 if ai == bj:
2025-07-02 06:41:16.677 if eqi is None:
2025-07-02 06:41:16.677 eqi, eqj = i, j
2025-07-02 06:41:16.677 continue
2025-07-02 06:41:16.677 cruncher.set_seq1(ai)
2025-07-02 06:41:16.678 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.678 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.678 # compares by a factor of 3.
2025-07-02 06:41:16.678 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.678 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.678 # of the computation is cached by cruncher
2025-07-02 06:41:16.678 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.678 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.678 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.678 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.678 if best_ratio < cutoff:
2025-07-02 06:41:16.678 # no non-identical "pretty close" pair
2025-07-02 06:41:16.678 if eqi is None:
2025-07-02 06:41:16.678 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.678 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.678 return
2025-07-02 06:41:16.678 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.678 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.678 else:
2025-07-02 06:41:16.679 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.679 eqi = None
2025-07-02 06:41:16.679
2025-07-02 06:41:16.679 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.679 # identical
2025-07-02 06:41:16.679
2025-07-02 06:41:16.679 # pump out diffs from before the synch point
2025-07-02 06:41:16.679 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.679
2025-07-02 06:41:16.679 # do intraline marking on the synch pair
2025-07-02 06:41:16.679 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.679 if eqi is None:
2025-07-02 06:41:16.679 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.679 atags = btags = ""
2025-07-02 06:41:16.679 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.679 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.679 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.679 if tag == 'replace':
2025-07-02 06:41:16.679 atags += '^' * la
2025-07-02 06:41:16.679 btags += '^' * lb
2025-07-02 06:41:16.680 elif tag == 'delete':
2025-07-02 06:41:16.680 atags += '-' * la
2025-07-02 06:41:16.680 elif tag == 'insert':
2025-07-02 06:41:16.680 btags += '+' * lb
2025-07-02 06:41:16.680 elif tag == 'equal':
2025-07-02 06:41:16.680 atags += ' ' * la
2025-07-02 06:41:16.680 btags += ' ' * lb
2025-07-02 06:41:16.680 else:
2025-07-02 06:41:16.680 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.680 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.680 else:
2025-07-02 06:41:16.680 # the synch pair is identical
2025-07-02 06:41:16.680 yield ' ' + aelt
2025-07-02 06:41:16.680
2025-07-02 06:41:16.680 # pump out diffs from after the synch point
2025-07-02 06:41:16.680 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.680
2025-07-02 06:41:16.680 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.680 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.681
2025-07-02 06:41:16.681 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.681 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.681 alo = 99, ahi = 1101
2025-07-02 06:41:16.681 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.681 blo = 99, bhi = 1101
2025-07-02 06:41:16.681
2025-07-02 06:41:16.681 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.681 g = []
2025-07-02 06:41:16.681 if alo < ahi:
2025-07-02 06:41:16.681 if blo < bhi:
2025-07-02 06:41:16.681 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.681 else:
2025-07-02 06:41:16.681 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.681 elif blo < bhi:
2025-07-02 06:41:16.681 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.681
2025-07-02 06:41:16.681 > yield from g
2025-07-02 06:41:16.681
2025-07-02 06:41:16.682 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.682 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.682
2025-07-02 06:41:16.682 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.682 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.682 alo = 99, ahi = 1101
2025-07-02 06:41:16.682 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.682 blo = 99, bhi = 1101
2025-07-02 06:41:16.682
2025-07-02 06:41:16.682 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.682 r"""
2025-07-02 06:41:16.682 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.682 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.682 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.682 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.682
2025-07-02 06:41:16.682 Example:
2025-07-02 06:41:16.683
2025-07-02 06:41:16.683 >>> d = Differ()
2025-07-02 06:41:16.683 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.683 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.683 >>> print(''.join(results), end="")
2025-07-02 06:41:16.683 - abcDefghiJkl
2025-07-02 06:41:16.683 + abcdefGhijkl
2025-07-02 06:41:16.683 """
2025-07-02 06:41:16.683
2025-07-02 06:41:16.683 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.683 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.683 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.683 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.683 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.683
2025-07-02 06:41:16.683 # search for the pair that matches best without being identical
2025-07-02 06:41:16.683 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.684 # on junk -- unless we have to)
2025-07-02 06:41:16.684 for j in range(blo, bhi):
2025-07-02 06:41:16.684 bj = b[j]
2025-07-02 06:41:16.684 cruncher.set_seq2(bj)
2025-07-02 06:41:16.684 for i in range(alo, ahi):
2025-07-02 06:41:16.684 ai = a[i]
2025-07-02 06:41:16.684 if ai == bj:
2025-07-02 06:41:16.684 if eqi is None:
2025-07-02 06:41:16.684 eqi, eqj = i, j
2025-07-02 06:41:16.684 continue
2025-07-02 06:41:16.684 cruncher.set_seq1(ai)
2025-07-02 06:41:16.684 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.684 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.684 # compares by a factor of 3.
2025-07-02 06:41:16.684 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.684 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.684 # of the computation is cached by cruncher
2025-07-02 06:41:16.684 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.684 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.684 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.685 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.685 if best_ratio < cutoff:
2025-07-02 06:41:16.685 # no non-identical "pretty close" pair
2025-07-02 06:41:16.685 if eqi is None:
2025-07-02 06:41:16.685 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.685 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.685 return
2025-07-02 06:41:16.685 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.685 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.685 else:
2025-07-02 06:41:16.685 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.685 eqi = None
2025-07-02 06:41:16.685
2025-07-02 06:41:16.685 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.685 # identical
2025-07-02 06:41:16.685
2025-07-02 06:41:16.685 # pump out diffs from before the synch point
2025-07-02 06:41:16.685 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.685
2025-07-02 06:41:16.686 # do intraline marking on the synch pair
2025-07-02 06:41:16.686 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.686 if eqi is None:
2025-07-02 06:41:16.686 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.686 atags = btags = ""
2025-07-02 06:41:16.686 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.686 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.686 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.686 if tag == 'replace':
2025-07-02 06:41:16.686 atags += '^' * la
2025-07-02 06:41:16.686 btags += '^' * lb
2025-07-02 06:41:16.686 elif tag == 'delete':
2025-07-02 06:41:16.686 atags += '-' * la
2025-07-02 06:41:16.686 elif tag == 'insert':
2025-07-02 06:41:16.686 btags += '+' * lb
2025-07-02 06:41:16.686 elif tag == 'equal':
2025-07-02 06:41:16.686 atags += ' ' * la
2025-07-02 06:41:16.686 btags += ' ' * lb
2025-07-02 06:41:16.686 else:
2025-07-02 06:41:16.687 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.687 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.687 else:
2025-07-02 06:41:16.687 # the synch pair is identical
2025-07-02 06:41:16.687 yield ' ' + aelt
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687 # pump out diffs from after the synch point
2025-07-02 06:41:16.687 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.687 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.687 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.687 alo = 100, ahi = 1101
2025-07-02 06:41:16.687 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.687 blo = 100, bhi = 1101
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.688 g = []
2025-07-02 06:41:16.688 if alo < ahi:
2025-07-02 06:41:16.688 if blo < bhi:
2025-07-02 06:41:16.688 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.688 else:
2025-07-02 06:41:16.688 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.688 elif blo < bhi:
2025-07-02 06:41:16.688 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.688
2025-07-02 06:41:16.688 > yield from g
2025-07-02 06:41:16.688
2025-07-02 06:41:16.688 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.688 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.688
2025-07-02 06:41:16.688 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.688 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.688 alo = 100, ahi = 1101
2025-07-02 06:41:16.688 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.688 blo = 100, bhi = 1101
2025-07-02 06:41:16.688
2025-07-02 06:41:16.689 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.689 r"""
2025-07-02 06:41:16.689 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.689 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.689 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.689 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.689
2025-07-02 06:41:16.689 Example:
2025-07-02 06:41:16.689
2025-07-02 06:41:16.689 >>> d = Differ()
2025-07-02 06:41:16.689 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.689 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.689 >>> print(''.join(results), end="")
2025-07-02 06:41:16.689 - abcDefghiJkl
2025-07-02 06:41:16.689 + abcdefGhijkl
2025-07-02 06:41:16.689 """
2025-07-02 06:41:16.689
2025-07-02 06:41:16.690 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.690 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.690 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.690 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.690 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.690
2025-07-02 06:41:16.690 # search for the pair that matches best without being identical
2025-07-02 06:41:16.690 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.690 # on junk -- unless we have to)
2025-07-02 06:41:16.690 for j in range(blo, bhi):
2025-07-02 06:41:16.690 bj = b[j]
2025-07-02 06:41:16.690 cruncher.set_seq2(bj)
2025-07-02 06:41:16.690 for i in range(alo, ahi):
2025-07-02 06:41:16.690 ai = a[i]
2025-07-02 06:41:16.690 if ai == bj:
2025-07-02 06:41:16.690 if eqi is None:
2025-07-02 06:41:16.690 eqi, eqj = i, j
2025-07-02 06:41:16.690 continue
2025-07-02 06:41:16.690 cruncher.set_seq1(ai)
2025-07-02 06:41:16.690 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.691 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.691 # compares by a factor of 3.
2025-07-02 06:41:16.691 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.691 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.691 # of the computation is cached by cruncher
2025-07-02 06:41:16.691 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.691 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.691 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.691 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.691 if best_ratio < cutoff:
2025-07-02 06:41:16.691 # no non-identical "pretty close" pair
2025-07-02 06:41:16.691 if eqi is None:
2025-07-02 06:41:16.691 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.691 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.691 return
2025-07-02 06:41:16.691 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.691 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.691 else:
2025-07-02 06:41:16.691 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.692 eqi = None
2025-07-02 06:41:16.692
2025-07-02 06:41:16.692 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.692 # identical
2025-07-02 06:41:16.692
2025-07-02 06:41:16.692 # pump out diffs from before the synch point
2025-07-02 06:41:16.692 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.692
2025-07-02 06:41:16.692 # do intraline marking on the synch pair
2025-07-02 06:41:16.692 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.692 if eqi is None:
2025-07-02 06:41:16.692 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.692 atags = btags = ""
2025-07-02 06:41:16.692 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.692 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.692 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.692 if tag == 'replace':
2025-07-02 06:41:16.692 atags += '^' * la
2025-07-02 06:41:16.692 btags += '^' * lb
2025-07-02 06:41:16.693 elif tag == 'delete':
2025-07-02 06:41:16.693 atags += '-' * la
2025-07-02 06:41:16.693 elif tag == 'insert':
2025-07-02 06:41:16.693 btags += '+' * lb
2025-07-02 06:41:16.693 elif tag == 'equal':
2025-07-02 06:41:16.693 atags += ' ' * la
2025-07-02 06:41:16.693 btags += ' ' * lb
2025-07-02 06:41:16.693 else:
2025-07-02 06:41:16.693 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.693 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.693 else:
2025-07-02 06:41:16.693 # the synch pair is identical
2025-07-02 06:41:16.693 yield ' ' + aelt
2025-07-02 06:41:16.693
2025-07-02 06:41:16.693 # pump out diffs from after the synch point
2025-07-02 06:41:16.693 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.693
2025-07-02 06:41:16.693 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.693 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.694
2025-07-02 06:41:16.694 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.694 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.694 alo = 101, ahi = 1101
2025-07-02 06:41:16.694 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.694 blo = 101, bhi = 1101
2025-07-02 06:41:16.694
2025-07-02 06:41:16.694 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.694 g = []
2025-07-02 06:41:16.694 if alo < ahi:
2025-07-02 06:41:16.694 if blo < bhi:
2025-07-02 06:41:16.694 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.694 else:
2025-07-02 06:41:16.694 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.694 elif blo < bhi:
2025-07-02 06:41:16.694 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.694
2025-07-02 06:41:16.694 > yield from g
2025-07-02 06:41:16.694
2025-07-02 06:41:16.695 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.695 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.695 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.695 alo = 101, ahi = 1101
2025-07-02 06:41:16.695 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.695 blo = 101, bhi = 1101
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.695 r"""
2025-07-02 06:41:16.695 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.695 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.695 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.695 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695 Example:
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695 >>> d = Differ()
2025-07-02 06:41:16.696 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.696 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.696 >>> print(''.join(results), end="")
2025-07-02 06:41:16.696 - abcDefghiJkl
2025-07-02 06:41:16.696 + abcdefGhijkl
2025-07-02 06:41:16.696 """
2025-07-02 06:41:16.696
2025-07-02 06:41:16.696 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.696 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.696 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.696 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.696 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.696
2025-07-02 06:41:16.696 # search for the pair that matches best without being identical
2025-07-02 06:41:16.696 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.696 # on junk -- unless we have to)
2025-07-02 06:41:16.696 for j in range(blo, bhi):
2025-07-02 06:41:16.696 bj = b[j]
2025-07-02 06:41:16.697 cruncher.set_seq2(bj)
2025-07-02 06:41:16.697 for i in range(alo, ahi):
2025-07-02 06:41:16.697 ai = a[i]
2025-07-02 06:41:16.697 if ai == bj:
2025-07-02 06:41:16.697 if eqi is None:
2025-07-02 06:41:16.697 eqi, eqj = i, j
2025-07-02 06:41:16.697 continue
2025-07-02 06:41:16.697 cruncher.set_seq1(ai)
2025-07-02 06:41:16.697 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.697 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.697 # compares by a factor of 3.
2025-07-02 06:41:16.697 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.697 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.697 # of the computation is cached by cruncher
2025-07-02 06:41:16.697 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.697 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.697 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.698 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.698 if best_ratio < cutoff:
2025-07-02 06:41:16.698 # no non-identical "pretty close" pair
2025-07-02 06:41:16.698 if eqi is None:
2025-07-02 06:41:16.698 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.698 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.698 return
2025-07-02 06:41:16.698 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.698 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.698 else:
2025-07-02 06:41:16.698 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.698 eqi = None
2025-07-02 06:41:16.698
2025-07-02 06:41:16.698 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.698 # identical
2025-07-02 06:41:16.698
2025-07-02 06:41:16.698 # pump out diffs from before the synch point
2025-07-02 06:41:16.698 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.698
2025-07-02 06:41:16.699 # do intraline marking on the synch pair
2025-07-02 06:41:16.699 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.699 if eqi is None:
2025-07-02 06:41:16.699 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.699 atags = btags = ""
2025-07-02 06:41:16.699 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.699 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.699 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.699 if tag == 'replace':
2025-07-02 06:41:16.699 atags += '^' * la
2025-07-02 06:41:16.699 btags += '^' * lb
2025-07-02 06:41:16.699 elif tag == 'delete':
2025-07-02 06:41:16.699 atags += '-' * la
2025-07-02 06:41:16.699 elif tag == 'insert':
2025-07-02 06:41:16.699 btags += '+' * lb
2025-07-02 06:41:16.699 elif tag == 'equal':
2025-07-02 06:41:16.699 atags += ' ' * la
2025-07-02 06:41:16.699 btags += ' ' * lb
2025-07-02 06:41:16.699 else:
2025-07-02 06:41:16.699 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.700 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.700 else:
2025-07-02 06:41:16.700 # the synch pair is identical
2025-07-02 06:41:16.700 yield ' ' + aelt
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700 # pump out diffs from after the synch point
2025-07-02 06:41:16.700 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.700 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.700 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.700 alo = 102, ahi = 1101
2025-07-02 06:41:16.700 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.700 blo = 102, bhi = 1101
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.701 g = []
2025-07-02 06:41:16.701 if alo < ahi:
2025-07-02 06:41:16.701 if blo < bhi:
2025-07-02 06:41:16.701 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.701 else:
2025-07-02 06:41:16.701 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.701 elif blo < bhi:
2025-07-02 06:41:16.701 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.701
2025-07-02 06:41:16.701 > yield from g
2025-07-02 06:41:16.701
2025-07-02 06:41:16.701 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.701 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.701
2025-07-02 06:41:16.701 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.701 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.701 alo = 102, ahi = 1101
2025-07-02 06:41:16.701 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.701 blo = 102, bhi = 1101
2025-07-02 06:41:16.702
2025-07-02 06:41:16.702 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.702 r"""
2025-07-02 06:41:16.702 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.702 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.702 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.702 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.702
2025-07-02 06:41:16.702 Example:
2025-07-02 06:41:16.702
2025-07-02 06:41:16.702 >>> d = Differ()
2025-07-02 06:41:16.702 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.702 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.702 >>> print(''.join(results), end="")
2025-07-02 06:41:16.702 - abcDefghiJkl
2025-07-02 06:41:16.702 + abcdefGhijkl
2025-07-02 06:41:16.702 """
2025-07-02 06:41:16.702
2025-07-02 06:41:16.703 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.703 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.703 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.703 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.703 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.703
2025-07-02 06:41:16.703 # search for the pair that matches best without being identical
2025-07-02 06:41:16.703 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.703 # on junk -- unless we have to)
2025-07-02 06:41:16.703 for j in range(blo, bhi):
2025-07-02 06:41:16.703 bj = b[j]
2025-07-02 06:41:16.703 cruncher.set_seq2(bj)
2025-07-02 06:41:16.703 for i in range(alo, ahi):
2025-07-02 06:41:16.703 ai = a[i]
2025-07-02 06:41:16.703 if ai == bj:
2025-07-02 06:41:16.703 if eqi is None:
2025-07-02 06:41:16.703 eqi, eqj = i, j
2025-07-02 06:41:16.703 continue
2025-07-02 06:41:16.703 cruncher.set_seq1(ai)
2025-07-02 06:41:16.703 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.704 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.704 # compares by a factor of 3.
2025-07-02 06:41:16.704 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.704 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.704 # of the computation is cached by cruncher
2025-07-02 06:41:16.704 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.704 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.704 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.704 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.704 if best_ratio < cutoff:
2025-07-02 06:41:16.704 # no non-identical "pretty close" pair
2025-07-02 06:41:16.704 if eqi is None:
2025-07-02 06:41:16.704 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.704 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.704 return
2025-07-02 06:41:16.704 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.704 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.704 else:
2025-07-02 06:41:16.704 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.705 eqi = None
2025-07-02 06:41:16.705
2025-07-02 06:41:16.705 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.705 # identical
2025-07-02 06:41:16.705
2025-07-02 06:41:16.705 # pump out diffs from before the synch point
2025-07-02 06:41:16.705 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.705
2025-07-02 06:41:16.705 # do intraline marking on the synch pair
2025-07-02 06:41:16.705 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.705 if eqi is None:
2025-07-02 06:41:16.705 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.705 atags = btags = ""
2025-07-02 06:41:16.705 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.705 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.705 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.705 if tag == 'replace':
2025-07-02 06:41:16.705 atags += '^' * la
2025-07-02 06:41:16.705 btags += '^' * lb
2025-07-02 06:41:16.706 elif tag == 'delete':
2025-07-02 06:41:16.706 atags += '-' * la
2025-07-02 06:41:16.706 elif tag == 'insert':
2025-07-02 06:41:16.706 btags += '+' * lb
2025-07-02 06:41:16.706 elif tag == 'equal':
2025-07-02 06:41:16.706 atags += ' ' * la
2025-07-02 06:41:16.706 btags += ' ' * lb
2025-07-02 06:41:16.706 else:
2025-07-02 06:41:16.706 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.706 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.706 else:
2025-07-02 06:41:16.706 # the synch pair is identical
2025-07-02 06:41:16.706 yield ' ' + aelt
2025-07-02 06:41:16.706
2025-07-02 06:41:16.706 # pump out diffs from after the synch point
2025-07-02 06:41:16.706 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.706
2025-07-02 06:41:16.706 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.706 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.706
2025-07-02 06:41:16.707 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.707 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.707 alo = 103, ahi = 1101
2025-07-02 06:41:16.707 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.707 blo = 103, bhi = 1101
2025-07-02 06:41:16.707
2025-07-02 06:41:16.707 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.707 g = []
2025-07-02 06:41:16.707 if alo < ahi:
2025-07-02 06:41:16.707 if blo < bhi:
2025-07-02 06:41:16.707 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.707 else:
2025-07-02 06:41:16.707 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.707 elif blo < bhi:
2025-07-02 06:41:16.707 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.707
2025-07-02 06:41:16.707 > yield from g
2025-07-02 06:41:16.707
2025-07-02 06:41:16.707 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.708 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.708 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.708 alo = 103, ahi = 1101
2025-07-02 06:41:16.708 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.708 blo = 103, bhi = 1101
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.708 r"""
2025-07-02 06:41:16.708 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.708 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.708 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.708 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708 Example:
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708 >>> d = Differ()
2025-07-02 06:41:16.708 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.709 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.709 >>> print(''.join(results), end="")
2025-07-02 06:41:16.709 - abcDefghiJkl
2025-07-02 06:41:16.709 + abcdefGhijkl
2025-07-02 06:41:16.709 """
2025-07-02 06:41:16.709
2025-07-02 06:41:16.709 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.709 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.709 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.709 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.709 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.709
2025-07-02 06:41:16.709 # search for the pair that matches best without being identical
2025-07-02 06:41:16.709 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.709 # on junk -- unless we have to)
2025-07-02 06:41:16.709 for j in range(blo, bhi):
2025-07-02 06:41:16.709 bj = b[j]
2025-07-02 06:41:16.710 cruncher.set_seq2(bj)
2025-07-02 06:41:16.710 for i in range(alo, ahi):
2025-07-02 06:41:16.710 ai = a[i]
2025-07-02 06:41:16.710 if ai == bj:
2025-07-02 06:41:16.710 if eqi is None:
2025-07-02 06:41:16.710 eqi, eqj = i, j
2025-07-02 06:41:16.710 continue
2025-07-02 06:41:16.710 cruncher.set_seq1(ai)
2025-07-02 06:41:16.710 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.710 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.710 # compares by a factor of 3.
2025-07-02 06:41:16.710 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.710 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.710 # of the computation is cached by cruncher
2025-07-02 06:41:16.710 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.710 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.710 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.710 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.710 if best_ratio < cutoff:
2025-07-02 06:41:16.711 # no non-identical "pretty close" pair
2025-07-02 06:41:16.711 if eqi is None:
2025-07-02 06:41:16.711 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.711 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.711 return
2025-07-02 06:41:16.711 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.711 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.711 else:
2025-07-02 06:41:16.711 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.711 eqi = None
2025-07-02 06:41:16.711
2025-07-02 06:41:16.711 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.711 # identical
2025-07-02 06:41:16.711
2025-07-02 06:41:16.711 # pump out diffs from before the synch point
2025-07-02 06:41:16.711 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.711
2025-07-02 06:41:16.711 # do intraline marking on the synch pair
2025-07-02 06:41:16.711 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.712 if eqi is None:
2025-07-02 06:41:16.712 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.712 atags = btags = ""
2025-07-02 06:41:16.712 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.712 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.712 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.712 if tag == 'replace':
2025-07-02 06:41:16.712 atags += '^' * la
2025-07-02 06:41:16.712 btags += '^' * lb
2025-07-02 06:41:16.712 elif tag == 'delete':
2025-07-02 06:41:16.712 atags += '-' * la
2025-07-02 06:41:16.712 elif tag == 'insert':
2025-07-02 06:41:16.712 btags += '+' * lb
2025-07-02 06:41:16.712 elif tag == 'equal':
2025-07-02 06:41:16.712 atags += ' ' * la
2025-07-02 06:41:16.712 btags += ' ' * lb
2025-07-02 06:41:16.712 else:
2025-07-02 06:41:16.712 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.712 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.712 else:
2025-07-02 06:41:16.713 # the synch pair is identical
2025-07-02 06:41:16.713 yield ' ' + aelt
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713 # pump out diffs from after the synch point
2025-07-02 06:41:16.713 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.713 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.713 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.713 alo = 104, ahi = 1101
2025-07-02 06:41:16.713 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.713 blo = 104, bhi = 1101
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.714 g = []
2025-07-02 06:41:16.714 if alo < ahi:
2025-07-02 06:41:16.714 if blo < bhi:
2025-07-02 06:41:16.714 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.714 else:
2025-07-02 06:41:16.714 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.714 elif blo < bhi:
2025-07-02 06:41:16.714 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.714
2025-07-02 06:41:16.714 > yield from g
2025-07-02 06:41:16.714
2025-07-02 06:41:16.714 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.714 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.714
2025-07-02 06:41:16.714 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.714 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.714 alo = 104, ahi = 1101
2025-07-02 06:41:16.714 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.714 blo = 104, bhi = 1101
2025-07-02 06:41:16.714
2025-07-02 06:41:16.715 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.715 r"""
2025-07-02 06:41:16.715 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.715 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.715 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.715 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.715
2025-07-02 06:41:16.715 Example:
2025-07-02 06:41:16.715
2025-07-02 06:41:16.715 >>> d = Differ()
2025-07-02 06:41:16.715 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.715 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.715 >>> print(''.join(results), end="")
2025-07-02 06:41:16.715 - abcDefghiJkl
2025-07-02 06:41:16.715 + abcdefGhijkl
2025-07-02 06:41:16.715 """
2025-07-02 06:41:16.715
2025-07-02 06:41:16.716 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.716 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.716 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.716 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.716 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.716
2025-07-02 06:41:16.716 # search for the pair that matches best without being identical
2025-07-02 06:41:16.716 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.716 # on junk -- unless we have to)
2025-07-02 06:41:16.716 for j in range(blo, bhi):
2025-07-02 06:41:16.716 bj = b[j]
2025-07-02 06:41:16.716 cruncher.set_seq2(bj)
2025-07-02 06:41:16.716 for i in range(alo, ahi):
2025-07-02 06:41:16.716 ai = a[i]
2025-07-02 06:41:16.716 if ai == bj:
2025-07-02 06:41:16.716 if eqi is None:
2025-07-02 06:41:16.716 eqi, eqj = i, j
2025-07-02 06:41:16.716 continue
2025-07-02 06:41:16.716 cruncher.set_seq1(ai)
2025-07-02 06:41:16.716 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.717 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.717 # compares by a factor of 3.
2025-07-02 06:41:16.717 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.717 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.717 # of the computation is cached by cruncher
2025-07-02 06:41:16.717 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.717 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.717 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.717 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.717 if best_ratio < cutoff:
2025-07-02 06:41:16.717 # no non-identical "pretty close" pair
2025-07-02 06:41:16.717 if eqi is None:
2025-07-02 06:41:16.717 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.717 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.717 return
2025-07-02 06:41:16.717 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.717 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.717 else:
2025-07-02 06:41:16.717 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.718 eqi = None
2025-07-02 06:41:16.718
2025-07-02 06:41:16.718 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.718 # identical
2025-07-02 06:41:16.718
2025-07-02 06:41:16.718 # pump out diffs from before the synch point
2025-07-02 06:41:16.718 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.718
2025-07-02 06:41:16.718 # do intraline marking on the synch pair
2025-07-02 06:41:16.718 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.718 if eqi is None:
2025-07-02 06:41:16.718 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.718 atags = btags = ""
2025-07-02 06:41:16.718 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.718 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.718 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.718 if tag == 'replace':
2025-07-02 06:41:16.718 atags += '^' * la
2025-07-02 06:41:16.718 btags += '^' * lb
2025-07-02 06:41:16.719 elif tag == 'delete':
2025-07-02 06:41:16.719 atags += '-' * la
2025-07-02 06:41:16.719 elif tag == 'insert':
2025-07-02 06:41:16.719 btags += '+' * lb
2025-07-02 06:41:16.719 elif tag == 'equal':
2025-07-02 06:41:16.719 atags += ' ' * la
2025-07-02 06:41:16.719 btags += ' ' * lb
2025-07-02 06:41:16.719 else:
2025-07-02 06:41:16.719 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.719 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.719 else:
2025-07-02 06:41:16.719 # the synch pair is identical
2025-07-02 06:41:16.719 yield ' ' + aelt
2025-07-02 06:41:16.719
2025-07-02 06:41:16.719 # pump out diffs from after the synch point
2025-07-02 06:41:16.719 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.719
2025-07-02 06:41:16.719 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.719 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.720 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.720 alo = 105, ahi = 1101
2025-07-02 06:41:16.720 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.720 blo = 105, bhi = 1101
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.720 g = []
2025-07-02 06:41:16.720 if alo < ahi:
2025-07-02 06:41:16.720 if blo < bhi:
2025-07-02 06:41:16.720 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.720 else:
2025-07-02 06:41:16.720 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.720 elif blo < bhi:
2025-07-02 06:41:16.720 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 > yield from g
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.721 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.721
2025-07-02 06:41:16.721 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.721 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.721 alo = 105, ahi = 1101
2025-07-02 06:41:16.721 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.721 blo = 105, bhi = 1101
2025-07-02 06:41:16.721
2025-07-02 06:41:16.721 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.721 r"""
2025-07-02 06:41:16.721 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.721 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.721 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.721 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.721
2025-07-02 06:41:16.721 Example:
2025-07-02 06:41:16.721
2025-07-02 06:41:16.722 >>> d = Differ()
2025-07-02 06:41:16.722 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.722 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.722 >>> print(''.join(results), end="")
2025-07-02 06:41:16.722 - abcDefghiJkl
2025-07-02 06:41:16.722 + abcdefGhijkl
2025-07-02 06:41:16.722 """
2025-07-02 06:41:16.722
2025-07-02 06:41:16.722 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.722 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.722 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.722 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.722 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.722
2025-07-02 06:41:16.722 # search for the pair that matches best without being identical
2025-07-02 06:41:16.722 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.722 # on junk -- unless we have to)
2025-07-02 06:41:16.723 for j in range(blo, bhi):
2025-07-02 06:41:16.723 bj = b[j]
2025-07-02 06:41:16.723 cruncher.set_seq2(bj)
2025-07-02 06:41:16.723 for i in range(alo, ahi):
2025-07-02 06:41:16.723 ai = a[i]
2025-07-02 06:41:16.723 if ai == bj:
2025-07-02 06:41:16.723 if eqi is None:
2025-07-02 06:41:16.723 eqi, eqj = i, j
2025-07-02 06:41:16.723 continue
2025-07-02 06:41:16.723 cruncher.set_seq1(ai)
2025-07-02 06:41:16.723 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.723 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.723 # compares by a factor of 3.
2025-07-02 06:41:16.723 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.723 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.723 # of the computation is cached by cruncher
2025-07-02 06:41:16.723 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.723 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.723 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.724 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.724 if best_ratio < cutoff:
2025-07-02 06:41:16.724 # no non-identical "pretty close" pair
2025-07-02 06:41:16.724 if eqi is None:
2025-07-02 06:41:16.724 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.724 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.724 return
2025-07-02 06:41:16.724 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.724 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.724 else:
2025-07-02 06:41:16.724 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.724 eqi = None
2025-07-02 06:41:16.724
2025-07-02 06:41:16.724 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.724 # identical
2025-07-02 06:41:16.724
2025-07-02 06:41:16.724 # pump out diffs from before the synch point
2025-07-02 06:41:16.724 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.724
2025-07-02 06:41:16.724 # do intraline marking on the synch pair
2025-07-02 06:41:16.725 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.725 if eqi is None:
2025-07-02 06:41:16.725 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.725 atags = btags = ""
2025-07-02 06:41:16.725 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.725 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.725 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.725 if tag == 'replace':
2025-07-02 06:41:16.725 atags += '^' * la
2025-07-02 06:41:16.725 btags += '^' * lb
2025-07-02 06:41:16.725 elif tag == 'delete':
2025-07-02 06:41:16.725 atags += '-' * la
2025-07-02 06:41:16.725 elif tag == 'insert':
2025-07-02 06:41:16.725 btags += '+' * lb
2025-07-02 06:41:16.725 elif tag == 'equal':
2025-07-02 06:41:16.725 atags += ' ' * la
2025-07-02 06:41:16.725 btags += ' ' * lb
2025-07-02 06:41:16.725 else:
2025-07-02 06:41:16.725 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.726 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.726 else:
2025-07-02 06:41:16.726 # the synch pair is identical
2025-07-02 06:41:16.726 yield ' ' + aelt
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726 # pump out diffs from after the synch point
2025-07-02 06:41:16.726 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.726 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.726 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.726 alo = 106, ahi = 1101
2025-07-02 06:41:16.726 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.726 blo = 106, bhi = 1101
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.726 g = []
2025-07-02 06:41:16.727 if alo < ahi:
2025-07-02 06:41:16.727 if blo < bhi:
2025-07-02 06:41:16.727 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.727 else:
2025-07-02 06:41:16.727 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.727 elif blo < bhi:
2025-07-02 06:41:16.727 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.727
2025-07-02 06:41:16.727 > yield from g
2025-07-02 06:41:16.727
2025-07-02 06:41:16.727 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.727 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.727
2025-07-02 06:41:16.727 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.727 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.727 alo = 106, ahi = 1101
2025-07-02 06:41:16.727 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.727 blo = 106, bhi = 1101
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.728 r"""
2025-07-02 06:41:16.728 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.728 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.728 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.728 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728 Example:
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728 >>> d = Differ()
2025-07-02 06:41:16.728 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.728 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.728 >>> print(''.join(results), end="")
2025-07-02 06:41:16.728 - abcDefghiJkl
2025-07-02 06:41:16.728 + abcdefGhijkl
2025-07-02 06:41:16.728 """
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.729 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.729 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.729 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.729 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.729
2025-07-02 06:41:16.729 # search for the pair that matches best without being identical
2025-07-02 06:41:16.729 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.729 # on junk -- unless we have to)
2025-07-02 06:41:16.729 for j in range(blo, bhi):
2025-07-02 06:41:16.729 bj = b[j]
2025-07-02 06:41:16.729 cruncher.set_seq2(bj)
2025-07-02 06:41:16.729 for i in range(alo, ahi):
2025-07-02 06:41:16.729 ai = a[i]
2025-07-02 06:41:16.729 if ai == bj:
2025-07-02 06:41:16.729 if eqi is None:
2025-07-02 06:41:16.729 eqi, eqj = i, j
2025-07-02 06:41:16.729 continue
2025-07-02 06:41:16.729 cruncher.set_seq1(ai)
2025-07-02 06:41:16.730 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.730 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.730 # compares by a factor of 3.
2025-07-02 06:41:16.730 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.730 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.730 # of the computation is cached by cruncher
2025-07-02 06:41:16.730 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.730 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.730 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.730 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.730 if best_ratio < cutoff:
2025-07-02 06:41:16.730 # no non-identical "pretty close" pair
2025-07-02 06:41:16.730 if eqi is None:
2025-07-02 06:41:16.730 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.730 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.730 return
2025-07-02 06:41:16.730 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.730 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.730 else:
2025-07-02 06:41:16.731 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.731 eqi = None
2025-07-02 06:41:16.731
2025-07-02 06:41:16.731 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.731 # identical
2025-07-02 06:41:16.731
2025-07-02 06:41:16.731 # pump out diffs from before the synch point
2025-07-02 06:41:16.731 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.731
2025-07-02 06:41:16.731 # do intraline marking on the synch pair
2025-07-02 06:41:16.731 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.731 if eqi is None:
2025-07-02 06:41:16.731 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.731 atags = btags = ""
2025-07-02 06:41:16.731 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.731 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.731 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.731 if tag == 'replace':
2025-07-02 06:41:16.731 atags += '^' * la
2025-07-02 06:41:16.731 btags += '^' * lb
2025-07-02 06:41:16.732 elif tag == 'delete':
2025-07-02 06:41:16.732 atags += '-' * la
2025-07-02 06:41:16.732 elif tag == 'insert':
2025-07-02 06:41:16.732 btags += '+' * lb
2025-07-02 06:41:16.732 elif tag == 'equal':
2025-07-02 06:41:16.732 atags += ' ' * la
2025-07-02 06:41:16.732 btags += ' ' * lb
2025-07-02 06:41:16.732 else:
2025-07-02 06:41:16.732 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.732 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.732 else:
2025-07-02 06:41:16.732 # the synch pair is identical
2025-07-02 06:41:16.732 yield ' ' + aelt
2025-07-02 06:41:16.732
2025-07-02 06:41:16.732 # pump out diffs from after the synch point
2025-07-02 06:41:16.732 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.732
2025-07-02 06:41:16.732 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.732 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.733
2025-07-02 06:41:16.733 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.733 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.733 alo = 107, ahi = 1101
2025-07-02 06:41:16.733 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.733 blo = 107, bhi = 1101
2025-07-02 06:41:16.733
2025-07-02 06:41:16.733 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.733 g = []
2025-07-02 06:41:16.733 if alo < ahi:
2025-07-02 06:41:16.733 if blo < bhi:
2025-07-02 06:41:16.733 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.733 else:
2025-07-02 06:41:16.733 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.733 elif blo < bhi:
2025-07-02 06:41:16.733 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.733
2025-07-02 06:41:16.733 > yield from g
2025-07-02 06:41:16.733
2025-07-02 06:41:16.734 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.734 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.734 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.734 alo = 107, ahi = 1101
2025-07-02 06:41:16.734 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.734 blo = 107, bhi = 1101
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.734 r"""
2025-07-02 06:41:16.734 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.734 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.734 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.734 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734 Example:
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734 >>> d = Differ()
2025-07-02 06:41:16.735 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.735 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.735 >>> print(''.join(results), end="")
2025-07-02 06:41:16.735 - abcDefghiJkl
2025-07-02 06:41:16.735 + abcdefGhijkl
2025-07-02 06:41:16.735 """
2025-07-02 06:41:16.735
2025-07-02 06:41:16.735 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.735 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.735 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.735 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.735 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.735
2025-07-02 06:41:16.735 # search for the pair that matches best without being identical
2025-07-02 06:41:16.735 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.735 # on junk -- unless we have to)
2025-07-02 06:41:16.735 for j in range(blo, bhi):
2025-07-02 06:41:16.735 bj = b[j]
2025-07-02 06:41:16.736 cruncher.set_seq2(bj)
2025-07-02 06:41:16.736 for i in range(alo, ahi):
2025-07-02 06:41:16.736 ai = a[i]
2025-07-02 06:41:16.736 if ai == bj:
2025-07-02 06:41:16.736 if eqi is None:
2025-07-02 06:41:16.736 eqi, eqj = i, j
2025-07-02 06:41:16.736 continue
2025-07-02 06:41:16.736 cruncher.set_seq1(ai)
2025-07-02 06:41:16.736 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.736 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.736 # compares by a factor of 3.
2025-07-02 06:41:16.736 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.736 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.736 # of the computation is cached by cruncher
2025-07-02 06:41:16.736 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.736 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.736 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.736 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.736 if best_ratio < cutoff:
2025-07-02 06:41:16.737 # no non-identical "pretty close" pair
2025-07-02 06:41:16.737 if eqi is None:
2025-07-02 06:41:16.737 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.737 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.737 return
2025-07-02 06:41:16.737 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.737 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.737 else:
2025-07-02 06:41:16.737 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.737 eqi = None
2025-07-02 06:41:16.737
2025-07-02 06:41:16.737 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.737 # identical
2025-07-02 06:41:16.737
2025-07-02 06:41:16.737 # pump out diffs from before the synch point
2025-07-02 06:41:16.737 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.737
2025-07-02 06:41:16.737 # do intraline marking on the synch pair
2025-07-02 06:41:16.737 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.737 if eqi is None:
2025-07-02 06:41:16.738 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.738 atags = btags = ""
2025-07-02 06:41:16.738 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.738 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.738 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.738 if tag == 'replace':
2025-07-02 06:41:16.738 atags += '^' * la
2025-07-02 06:41:16.738 btags += '^' * lb
2025-07-02 06:41:16.738 elif tag == 'delete':
2025-07-02 06:41:16.738 atags += '-' * la
2025-07-02 06:41:16.738 elif tag == 'insert':
2025-07-02 06:41:16.738 btags += '+' * lb
2025-07-02 06:41:16.738 elif tag == 'equal':
2025-07-02 06:41:16.738 atags += ' ' * la
2025-07-02 06:41:16.738 btags += ' ' * lb
2025-07-02 06:41:16.738 else:
2025-07-02 06:41:16.738 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.738 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.738 else:
2025-07-02 06:41:16.739 # the synch pair is identical
2025-07-02 06:41:16.739 yield ' ' + aelt
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739 # pump out diffs from after the synch point
2025-07-02 06:41:16.739 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.739 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.739 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.739 alo = 108, ahi = 1101
2025-07-02 06:41:16.739 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.739 blo = 108, bhi = 1101
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.739 g = []
2025-07-02 06:41:16.739 if alo < ahi:
2025-07-02 06:41:16.739 if blo < bhi:
2025-07-02 06:41:16.740 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.740 else:
2025-07-02 06:41:16.740 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.740 elif blo < bhi:
2025-07-02 06:41:16.740 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 > yield from g
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.740 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.740 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.740 alo = 108, ahi = 1101
2025-07-02 06:41:16.740 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.740 blo = 108, bhi = 1101
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.740 r"""
2025-07-02 06:41:16.741 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.741 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.741 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.741 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.741
2025-07-02 06:41:16.741 Example:
2025-07-02 06:41:16.741
2025-07-02 06:41:16.741 >>> d = Differ()
2025-07-02 06:41:16.741 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.741 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.741 >>> print(''.join(results), end="")
2025-07-02 06:41:16.741 - abcDefghiJkl
2025-07-02 06:41:16.741 + abcdefGhijkl
2025-07-02 06:41:16.741 """
2025-07-02 06:41:16.741
2025-07-02 06:41:16.741 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.741 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.741 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.741 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.742 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.742
2025-07-02 06:41:16.742 # search for the pair that matches best without being identical
2025-07-02 06:41:16.742 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.742 # on junk -- unless we have to)
2025-07-02 06:41:16.742 for j in range(blo, bhi):
2025-07-02 06:41:16.742 bj = b[j]
2025-07-02 06:41:16.742 cruncher.set_seq2(bj)
2025-07-02 06:41:16.742 for i in range(alo, ahi):
2025-07-02 06:41:16.742 ai = a[i]
2025-07-02 06:41:16.742 if ai == bj:
2025-07-02 06:41:16.742 if eqi is None:
2025-07-02 06:41:16.742 eqi, eqj = i, j
2025-07-02 06:41:16.742 continue
2025-07-02 06:41:16.742 cruncher.set_seq1(ai)
2025-07-02 06:41:16.742 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.742 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.742 # compares by a factor of 3.
2025-07-02 06:41:16.742 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.742 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.743 # of the computation is cached by cruncher
2025-07-02 06:41:16.743 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.743 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.743 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.743 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.743 if best_ratio < cutoff:
2025-07-02 06:41:16.743 # no non-identical "pretty close" pair
2025-07-02 06:41:16.743 if eqi is None:
2025-07-02 06:41:16.743 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.743 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.743 return
2025-07-02 06:41:16.743 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.743 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.743 else:
2025-07-02 06:41:16.743 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.743 eqi = None
2025-07-02 06:41:16.743
2025-07-02 06:41:16.743 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.743 # identical
2025-07-02 06:41:16.743
2025-07-02 06:41:16.744 # pump out diffs from before the synch point
2025-07-02 06:41:16.744 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.744
2025-07-02 06:41:16.744 # do intraline marking on the synch pair
2025-07-02 06:41:16.744 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.744 if eqi is None:
2025-07-02 06:41:16.744 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.744 atags = btags = ""
2025-07-02 06:41:16.744 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.744 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.744 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.744 if tag == 'replace':
2025-07-02 06:41:16.744 atags += '^' * la
2025-07-02 06:41:16.744 btags += '^' * lb
2025-07-02 06:41:16.744 elif tag == 'delete':
2025-07-02 06:41:16.744 atags += '-' * la
2025-07-02 06:41:16.744 elif tag == 'insert':
2025-07-02 06:41:16.744 btags += '+' * lb
2025-07-02 06:41:16.744 elif tag == 'equal':
2025-07-02 06:41:16.744 atags += ' ' * la
2025-07-02 06:41:16.745 btags += ' ' * lb
2025-07-02 06:41:16.745 else:
2025-07-02 06:41:16.745 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.745 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.745 else:
2025-07-02 06:41:16.745 # the synch pair is identical
2025-07-02 06:41:16.745 yield ' ' + aelt
2025-07-02 06:41:16.745
2025-07-02 06:41:16.745 # pump out diffs from after the synch point
2025-07-02 06:41:16.745 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.745
2025-07-02 06:41:16.745 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.745 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.745
2025-07-02 06:41:16.745 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.745 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.745 alo = 109, ahi = 1101
2025-07-02 06:41:16.746 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.746 blo = 109, bhi = 1101
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.746 g = []
2025-07-02 06:41:16.746 if alo < ahi:
2025-07-02 06:41:16.746 if blo < bhi:
2025-07-02 06:41:16.746 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.746 else:
2025-07-02 06:41:16.746 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.746 elif blo < bhi:
2025-07-02 06:41:16.746 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 > yield from g
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.746 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.747 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.747 alo = 109, ahi = 1101
2025-07-02 06:41:16.747 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.747 blo = 109, bhi = 1101
2025-07-02 06:41:16.747
2025-07-02 06:41:16.747 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.747 r"""
2025-07-02 06:41:16.747 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.747 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.747 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.747 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.747
2025-07-02 06:41:16.747 Example:
2025-07-02 06:41:16.747
2025-07-02 06:41:16.747 >>> d = Differ()
2025-07-02 06:41:16.747 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.747 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.747 >>> print(''.join(results), end="")
2025-07-02 06:41:16.747 - abcDefghiJkl
2025-07-02 06:41:16.748 + abcdefGhijkl
2025-07-02 06:41:16.748 """
2025-07-02 06:41:16.748
2025-07-02 06:41:16.748 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.748 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.748 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.748 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.748 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.748
2025-07-02 06:41:16.748 # search for the pair that matches best without being identical
2025-07-02 06:41:16.748 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.748 # on junk -- unless we have to)
2025-07-02 06:41:16.748 for j in range(blo, bhi):
2025-07-02 06:41:16.748 bj = b[j]
2025-07-02 06:41:16.748 cruncher.set_seq2(bj)
2025-07-02 06:41:16.748 for i in range(alo, ahi):
2025-07-02 06:41:16.748 ai = a[i]
2025-07-02 06:41:16.748 if ai == bj:
2025-07-02 06:41:16.748 if eqi is None:
2025-07-02 06:41:16.749 eqi, eqj = i, j
2025-07-02 06:41:16.749 continue
2025-07-02 06:41:16.749 cruncher.set_seq1(ai)
2025-07-02 06:41:16.749 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.749 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.749 # compares by a factor of 3.
2025-07-02 06:41:16.749 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.749 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.749 # of the computation is cached by cruncher
2025-07-02 06:41:16.749 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.749 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.749 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.749 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.749 if best_ratio < cutoff:
2025-07-02 06:41:16.749 # no non-identical "pretty close" pair
2025-07-02 06:41:16.749 if eqi is None:
2025-07-02 06:41:16.749 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.749 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.749 return
2025-07-02 06:41:16.749 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.749 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.750 else:
2025-07-02 06:41:16.750 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.750 eqi = None
2025-07-02 06:41:16.750
2025-07-02 06:41:16.750 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.750 # identical
2025-07-02 06:41:16.750
2025-07-02 06:41:16.750 # pump out diffs from before the synch point
2025-07-02 06:41:16.750 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.750
2025-07-02 06:41:16.750 # do intraline marking on the synch pair
2025-07-02 06:41:16.750 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.750 if eqi is None:
2025-07-02 06:41:16.750 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.750 atags = btags = ""
2025-07-02 06:41:16.750 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.750 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.750 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.750 if tag == 'replace':
2025-07-02 06:41:16.750 atags += '^' * la
2025-07-02 06:41:16.751 btags += '^' * lb
2025-07-02 06:41:16.751 elif tag == 'delete':
2025-07-02 06:41:16.751 atags += '-' * la
2025-07-02 06:41:16.751 elif tag == 'insert':
2025-07-02 06:41:16.751 btags += '+' * lb
2025-07-02 06:41:16.751 elif tag == 'equal':
2025-07-02 06:41:16.751 atags += ' ' * la
2025-07-02 06:41:16.751 btags += ' ' * lb
2025-07-02 06:41:16.751 else:
2025-07-02 06:41:16.751 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.751 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.751 else:
2025-07-02 06:41:16.751 # the synch pair is identical
2025-07-02 06:41:16.751 yield ' ' + aelt
2025-07-02 06:41:16.751
2025-07-02 06:41:16.751 # pump out diffs from after the synch point
2025-07-02 06:41:16.751 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.751
2025-07-02 06:41:16.751 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.751 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.752 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.752 alo = 110, ahi = 1101
2025-07-02 06:41:16.752 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.752 blo = 110, bhi = 1101
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.752 g = []
2025-07-02 06:41:16.752 if alo < ahi:
2025-07-02 06:41:16.752 if blo < bhi:
2025-07-02 06:41:16.752 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.752 else:
2025-07-02 06:41:16.752 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.752 elif blo < bhi:
2025-07-02 06:41:16.752 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 > yield from g
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.752 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.753 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.753 alo = 110, ahi = 1101
2025-07-02 06:41:16.753 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.753 blo = 110, bhi = 1101
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.753 r"""
2025-07-02 06:41:16.753 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.753 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.753 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.753 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753 Example:
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753 >>> d = Differ()
2025-07-02 06:41:16.753 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.753 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.754 >>> print(''.join(results), end="")
2025-07-02 06:41:16.754 - abcDefghiJkl
2025-07-02 06:41:16.754 + abcdefGhijkl
2025-07-02 06:41:16.754 """
2025-07-02 06:41:16.754
2025-07-02 06:41:16.754 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.754 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.754 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.754 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.754 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.754
2025-07-02 06:41:16.754 # search for the pair that matches best without being identical
2025-07-02 06:41:16.754 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.754 # on junk -- unless we have to)
2025-07-02 06:41:16.754 for j in range(blo, bhi):
2025-07-02 06:41:16.754 bj = b[j]
2025-07-02 06:41:16.754 cruncher.set_seq2(bj)
2025-07-02 06:41:16.755 for i in range(alo, ahi):
2025-07-02 06:41:16.755 ai = a[i]
2025-07-02 06:41:16.755 if ai == bj:
2025-07-02 06:41:16.755 if eqi is None:
2025-07-02 06:41:16.755 eqi, eqj = i, j
2025-07-02 06:41:16.755 continue
2025-07-02 06:41:16.755 cruncher.set_seq1(ai)
2025-07-02 06:41:16.755 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.755 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.755 # compares by a factor of 3.
2025-07-02 06:41:16.755 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.755 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.755 # of the computation is cached by cruncher
2025-07-02 06:41:16.755 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.755 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.755 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.755 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.755 if best_ratio < cutoff:
2025-07-02 06:41:16.755 # no non-identical "pretty close" pair
2025-07-02 06:41:16.755 if eqi is None:
2025-07-02 06:41:16.756 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.756 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.756 return
2025-07-02 06:41:16.756 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.756 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.756 else:
2025-07-02 06:41:16.756 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.756 eqi = None
2025-07-02 06:41:16.756
2025-07-02 06:41:16.756 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.756 # identical
2025-07-02 06:41:16.756
2025-07-02 06:41:16.756 # pump out diffs from before the synch point
2025-07-02 06:41:16.756 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.756
2025-07-02 06:41:16.756 # do intraline marking on the synch pair
2025-07-02 06:41:16.756 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.756 if eqi is None:
2025-07-02 06:41:16.756 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.756 atags = btags = ""
2025-07-02 06:41:16.757 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.757 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.757 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.757 if tag == 'replace':
2025-07-02 06:41:16.757 atags += '^' * la
2025-07-02 06:41:16.757 btags += '^' * lb
2025-07-02 06:41:16.757 elif tag == 'delete':
2025-07-02 06:41:16.757 atags += '-' * la
2025-07-02 06:41:16.757 elif tag == 'insert':
2025-07-02 06:41:16.757 btags += '+' * lb
2025-07-02 06:41:16.757 elif tag == 'equal':
2025-07-02 06:41:16.757 atags += ' ' * la
2025-07-02 06:41:16.757 btags += ' ' * lb
2025-07-02 06:41:16.757 else:
2025-07-02 06:41:16.757 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.757 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.757 else:
2025-07-02 06:41:16.757 # the synch pair is identical
2025-07-02 06:41:16.757 yield ' ' + aelt
2025-07-02 06:41:16.757
2025-07-02 06:41:16.758 # pump out diffs from after the synch point
2025-07-02 06:41:16.758 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.758
2025-07-02 06:41:16.758 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.758 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.758
2025-07-02 06:41:16.758 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.758 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.758 alo = 111, ahi = 1101
2025-07-02 06:41:16.758 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.758 blo = 111, bhi = 1101
2025-07-02 06:41:16.758
2025-07-02 06:41:16.758 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.758 g = []
2025-07-02 06:41:16.758 if alo < ahi:
2025-07-02 06:41:16.758 if blo < bhi:
2025-07-02 06:41:16.758 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.758 else:
2025-07-02 06:41:16.758 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.758 elif blo < bhi:
2025-07-02 06:41:16.759 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 > yield from g
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.759 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.759 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.759 alo = 111, ahi = 1101
2025-07-02 06:41:16.759 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.759 blo = 111, bhi = 1101
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.759 r"""
2025-07-02 06:41:16.759 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.759 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.759 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.759 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.759
2025-07-02 06:41:16.760 Example:
2025-07-02 06:41:16.760
2025-07-02 06:41:16.760 >>> d = Differ()
2025-07-02 06:41:16.760 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.760 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.760 >>> print(''.join(results), end="")
2025-07-02 06:41:16.760 - abcDefghiJkl
2025-07-02 06:41:16.760 + abcdefGhijkl
2025-07-02 06:41:16.760 """
2025-07-02 06:41:16.760
2025-07-02 06:41:16.760 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.760 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.760 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.760 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.760 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.760
2025-07-02 06:41:16.760 # search for the pair that matches best without being identical
2025-07-02 06:41:16.760 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.761 # on junk -- unless we have to)
2025-07-02 06:41:16.761 for j in range(blo, bhi):
2025-07-02 06:41:16.761 bj = b[j]
2025-07-02 06:41:16.761 cruncher.set_seq2(bj)
2025-07-02 06:41:16.761 for i in range(alo, ahi):
2025-07-02 06:41:16.761 ai = a[i]
2025-07-02 06:41:16.761 if ai == bj:
2025-07-02 06:41:16.761 if eqi is None:
2025-07-02 06:41:16.761 eqi, eqj = i, j
2025-07-02 06:41:16.761 continue
2025-07-02 06:41:16.761 cruncher.set_seq1(ai)
2025-07-02 06:41:16.761 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.761 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.761 # compares by a factor of 3.
2025-07-02 06:41:16.761 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.761 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.761 # of the computation is cached by cruncher
2025-07-02 06:41:16.761 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.761 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.762 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.762 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.762 if best_ratio < cutoff:
2025-07-02 06:41:16.762 # no non-identical "pretty close" pair
2025-07-02 06:41:16.762 if eqi is None:
2025-07-02 06:41:16.762 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.762 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.762 return
2025-07-02 06:41:16.762 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.762 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.762 else:
2025-07-02 06:41:16.762 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.762 eqi = None
2025-07-02 06:41:16.762
2025-07-02 06:41:16.762 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.762 # identical
2025-07-02 06:41:16.762
2025-07-02 06:41:16.762 # pump out diffs from before the synch point
2025-07-02 06:41:16.763 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.763
2025-07-02 06:41:16.763 # do intraline marking on the synch pair
2025-07-02 06:41:16.763 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.763 if eqi is None:
2025-07-02 06:41:16.763 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.763 atags = btags = ""
2025-07-02 06:41:16.763 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.763 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.763 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.763 if tag == 'replace':
2025-07-02 06:41:16.763 atags += '^' * la
2025-07-02 06:41:16.763 btags += '^' * lb
2025-07-02 06:41:16.763 elif tag == 'delete':
2025-07-02 06:41:16.763 atags += '-' * la
2025-07-02 06:41:16.763 elif tag == 'insert':
2025-07-02 06:41:16.763 btags += '+' * lb
2025-07-02 06:41:16.763 elif tag == 'equal':
2025-07-02 06:41:16.764 atags += ' ' * la
2025-07-02 06:41:16.764 btags += ' ' * lb
2025-07-02 06:41:16.764 else:
2025-07-02 06:41:16.764 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.764 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.764 else:
2025-07-02 06:41:16.764 # the synch pair is identical
2025-07-02 06:41:16.764 yield ' ' + aelt
2025-07-02 06:41:16.764
2025-07-02 06:41:16.764 # pump out diffs from after the synch point
2025-07-02 06:41:16.764 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.764
2025-07-02 06:41:16.764 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.764 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.764
2025-07-02 06:41:16.764 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.764 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.764 alo = 114, ahi = 1101
2025-07-02 06:41:16.764 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.765 blo = 114, bhi = 1101
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.765 g = []
2025-07-02 06:41:16.765 if alo < ahi:
2025-07-02 06:41:16.765 if blo < bhi:
2025-07-02 06:41:16.765 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.765 else:
2025-07-02 06:41:16.765 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.765 elif blo < bhi:
2025-07-02 06:41:16.765 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 > yield from g
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.765 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.765 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.765 alo = 114, ahi = 1101
2025-07-02 06:41:16.766 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.766 blo = 114, bhi = 1101
2025-07-02 06:41:16.766
2025-07-02 06:41:16.766 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.766 r"""
2025-07-02 06:41:16.766 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.766 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.766 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.766 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.766
2025-07-02 06:41:16.766 Example:
2025-07-02 06:41:16.766
2025-07-02 06:41:16.766 >>> d = Differ()
2025-07-02 06:41:16.766 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.766 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.766 >>> print(''.join(results), end="")
2025-07-02 06:41:16.766 - abcDefghiJkl
2025-07-02 06:41:16.766 + abcdefGhijkl
2025-07-02 06:41:16.767 """
2025-07-02 06:41:16.767
2025-07-02 06:41:16.767 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.767 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.767 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.767 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.767 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.767
2025-07-02 06:41:16.767 # search for the pair that matches best without being identical
2025-07-02 06:41:16.767 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.767 # on junk -- unless we have to)
2025-07-02 06:41:16.767 for j in range(blo, bhi):
2025-07-02 06:41:16.767 bj = b[j]
2025-07-02 06:41:16.767 cruncher.set_seq2(bj)
2025-07-02 06:41:16.767 for i in range(alo, ahi):
2025-07-02 06:41:16.767 ai = a[i]
2025-07-02 06:41:16.767 if ai == bj:
2025-07-02 06:41:16.767 if eqi is None:
2025-07-02 06:41:16.767 eqi, eqj = i, j
2025-07-02 06:41:16.768 continue
2025-07-02 06:41:16.768 cruncher.set_seq1(ai)
2025-07-02 06:41:16.768 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.768 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.768 # compares by a factor of 3.
2025-07-02 06:41:16.768 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.768 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.768 # of the computation is cached by cruncher
2025-07-02 06:41:16.768 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.768 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.768 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.768 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.768 if best_ratio < cutoff:
2025-07-02 06:41:16.768 # no non-identical "pretty close" pair
2025-07-02 06:41:16.768 if eqi is None:
2025-07-02 06:41:16.768 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.768 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.768 return
2025-07-02 06:41:16.768 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.769 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.769 else:
2025-07-02 06:41:16.769 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.769 eqi = None
2025-07-02 06:41:16.769
2025-07-02 06:41:16.769 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.769 # identical
2025-07-02 06:41:16.769
2025-07-02 06:41:16.769 # pump out diffs from before the synch point
2025-07-02 06:41:16.769 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.769
2025-07-02 06:41:16.769 # do intraline marking on the synch pair
2025-07-02 06:41:16.769 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.769 if eqi is None:
2025-07-02 06:41:16.769 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.769 atags = btags = ""
2025-07-02 06:41:16.769 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.769 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.769 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.770 if tag == 'replace':
2025-07-02 06:41:16.770 atags += '^' * la
2025-07-02 06:41:16.770 btags += '^' * lb
2025-07-02 06:41:16.770 elif tag == 'delete':
2025-07-02 06:41:16.770 atags += '-' * la
2025-07-02 06:41:16.770 elif tag == 'insert':
2025-07-02 06:41:16.770 btags += '+' * lb
2025-07-02 06:41:16.770 elif tag == 'equal':
2025-07-02 06:41:16.770 atags += ' ' * la
2025-07-02 06:41:16.770 btags += ' ' * lb
2025-07-02 06:41:16.770 else:
2025-07-02 06:41:16.770 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.770 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.770 else:
2025-07-02 06:41:16.770 # the synch pair is identical
2025-07-02 06:41:16.770 yield ' ' + aelt
2025-07-02 06:41:16.770
2025-07-02 06:41:16.770 # pump out diffs from after the synch point
2025-07-02 06:41:16.770 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.770
2025-07-02 06:41:16.771 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.771 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.771
2025-07-02 06:41:16.771 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.771 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.771 alo = 115, ahi = 1101
2025-07-02 06:41:16.771 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.771 blo = 115, bhi = 1101
2025-07-02 06:41:16.771
2025-07-02 06:41:16.771 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.771 g = []
2025-07-02 06:41:16.771 if alo < ahi:
2025-07-02 06:41:16.771 if blo < bhi:
2025-07-02 06:41:16.771 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.771 else:
2025-07-02 06:41:16.771 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.771 elif blo < bhi:
2025-07-02 06:41:16.771 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 > yield from g
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.772 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.772 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.772 alo = 115, ahi = 1101
2025-07-02 06:41:16.772 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.772 blo = 115, bhi = 1101
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.772 r"""
2025-07-02 06:41:16.772 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.772 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.772 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.772 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 Example:
2025-07-02 06:41:16.773
2025-07-02 06:41:16.773 >>> d = Differ()
2025-07-02 06:41:16.773 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.773 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.773 >>> print(''.join(results), end="")
2025-07-02 06:41:16.773 - abcDefghiJkl
2025-07-02 06:41:16.773 + abcdefGhijkl
2025-07-02 06:41:16.773 """
2025-07-02 06:41:16.773
2025-07-02 06:41:16.773 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.773 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.773 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.773 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.773 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.773
2025-07-02 06:41:16.773 # search for the pair that matches best without being identical
2025-07-02 06:41:16.773 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.773 # on junk -- unless we have to)
2025-07-02 06:41:16.774 for j in range(blo, bhi):
2025-07-02 06:41:16.774 bj = b[j]
2025-07-02 06:41:16.774 cruncher.set_seq2(bj)
2025-07-02 06:41:16.774 for i in range(alo, ahi):
2025-07-02 06:41:16.774 ai = a[i]
2025-07-02 06:41:16.774 if ai == bj:
2025-07-02 06:41:16.774 if eqi is None:
2025-07-02 06:41:16.774 eqi, eqj = i, j
2025-07-02 06:41:16.774 continue
2025-07-02 06:41:16.774 cruncher.set_seq1(ai)
2025-07-02 06:41:16.774 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.774 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.774 # compares by a factor of 3.
2025-07-02 06:41:16.774 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.774 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.774 # of the computation is cached by cruncher
2025-07-02 06:41:16.774 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.774 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.774 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.774 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.775 if best_ratio < cutoff:
2025-07-02 06:41:16.775 # no non-identical "pretty close" pair
2025-07-02 06:41:16.775 if eqi is None:
2025-07-02 06:41:16.775 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.775 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.775 return
2025-07-02 06:41:16.775 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.775 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.775 else:
2025-07-02 06:41:16.775 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.775 eqi = None
2025-07-02 06:41:16.775
2025-07-02 06:41:16.775 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.775 # identical
2025-07-02 06:41:16.775
2025-07-02 06:41:16.775 # pump out diffs from before the synch point
2025-07-02 06:41:16.775 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.775
2025-07-02 06:41:16.775 # do intraline marking on the synch pair
2025-07-02 06:41:16.775 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.775 if eqi is None:
2025-07-02 06:41:16.776 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.776 atags = btags = ""
2025-07-02 06:41:16.776 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.776 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.776 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.776 if tag == 'replace':
2025-07-02 06:41:16.776 atags += '^' * la
2025-07-02 06:41:16.776 btags += '^' * lb
2025-07-02 06:41:16.776 elif tag == 'delete':
2025-07-02 06:41:16.776 atags += '-' * la
2025-07-02 06:41:16.776 elif tag == 'insert':
2025-07-02 06:41:16.776 btags += '+' * lb
2025-07-02 06:41:16.776 elif tag == 'equal':
2025-07-02 06:41:16.776 atags += ' ' * la
2025-07-02 06:41:16.776 btags += ' ' * lb
2025-07-02 06:41:16.776 else:
2025-07-02 06:41:16.776 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.776 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.776 else:
2025-07-02 06:41:16.776 # the synch pair is identical
2025-07-02 06:41:16.777 yield ' ' + aelt
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777 # pump out diffs from after the synch point
2025-07-02 06:41:16.777 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.777 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.777 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.777 alo = 116, ahi = 1101
2025-07-02 06:41:16.777 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.777 blo = 116, bhi = 1101
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.777 g = []
2025-07-02 06:41:16.777 if alo < ahi:
2025-07-02 06:41:16.777 if blo < bhi:
2025-07-02 06:41:16.778 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.778 else:
2025-07-02 06:41:16.778 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.778 elif blo < bhi:
2025-07-02 06:41:16.778 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 > yield from g
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.778 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.778 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.778 alo = 116, ahi = 1101
2025-07-02 06:41:16.778 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.778 blo = 116, bhi = 1101
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.778 r"""
2025-07-02 06:41:16.778 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.779 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.779 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.779 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.779
2025-07-02 06:41:16.779 Example:
2025-07-02 06:41:16.779
2025-07-02 06:41:16.779 >>> d = Differ()
2025-07-02 06:41:16.779 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.779 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.779 >>> print(''.join(results), end="")
2025-07-02 06:41:16.779 - abcDefghiJkl
2025-07-02 06:41:16.779 + abcdefGhijkl
2025-07-02 06:41:16.779 """
2025-07-02 06:41:16.779
2025-07-02 06:41:16.779 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.779 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.779 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.779 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.780 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.780
2025-07-02 06:41:16.780 # search for the pair that matches best without being identical
2025-07-02 06:41:16.780 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.780 # on junk -- unless we have to)
2025-07-02 06:41:16.780 for j in range(blo, bhi):
2025-07-02 06:41:16.780 bj = b[j]
2025-07-02 06:41:16.780 cruncher.set_seq2(bj)
2025-07-02 06:41:16.780 for i in range(alo, ahi):
2025-07-02 06:41:16.780 ai = a[i]
2025-07-02 06:41:16.780 if ai == bj:
2025-07-02 06:41:16.780 if eqi is None:
2025-07-02 06:41:16.780 eqi, eqj = i, j
2025-07-02 06:41:16.780 continue
2025-07-02 06:41:16.780 cruncher.set_seq1(ai)
2025-07-02 06:41:16.780 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.780 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.780 # compares by a factor of 3.
2025-07-02 06:41:16.780 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.781 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.781 # of the computation is cached by cruncher
2025-07-02 06:41:16.781 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.781 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.781 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.781 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.781 if best_ratio < cutoff:
2025-07-02 06:41:16.781 # no non-identical "pretty close" pair
2025-07-02 06:41:16.781 if eqi is None:
2025-07-02 06:41:16.781 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.781 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.781 return
2025-07-02 06:41:16.781 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.781 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.781 else:
2025-07-02 06:41:16.781 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.781 eqi = None
2025-07-02 06:41:16.781
2025-07-02 06:41:16.781 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.782 # identical
2025-07-02 06:41:16.782
2025-07-02 06:41:16.782 # pump out diffs from before the synch point
2025-07-02 06:41:16.782 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.782
2025-07-02 06:41:16.782 # do intraline marking on the synch pair
2025-07-02 06:41:16.782 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.782 if eqi is None:
2025-07-02 06:41:16.782 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.782 atags = btags = ""
2025-07-02 06:41:16.782 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.782 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.782 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.782 if tag == 'replace':
2025-07-02 06:41:16.782 atags += '^' * la
2025-07-02 06:41:16.782 btags += '^' * lb
2025-07-02 06:41:16.782 elif tag == 'delete':
2025-07-02 06:41:16.782 atags += '-' * la
2025-07-02 06:41:16.782 elif tag == 'insert':
2025-07-02 06:41:16.782 btags += '+' * lb
2025-07-02 06:41:16.783 elif tag == 'equal':
2025-07-02 06:41:16.783 atags += ' ' * la
2025-07-02 06:41:16.783 btags += ' ' * lb
2025-07-02 06:41:16.783 else:
2025-07-02 06:41:16.783 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.783 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.783 else:
2025-07-02 06:41:16.783 # the synch pair is identical
2025-07-02 06:41:16.783 yield ' ' + aelt
2025-07-02 06:41:16.783
2025-07-02 06:41:16.783 # pump out diffs from after the synch point
2025-07-02 06:41:16.783 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.783
2025-07-02 06:41:16.783 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.783 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.783
2025-07-02 06:41:16.783 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.783 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.783 alo = 117, ahi = 1101
2025-07-02 06:41:16.783 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.784 blo = 117, bhi = 1101
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.784 g = []
2025-07-02 06:41:16.784 if alo < ahi:
2025-07-02 06:41:16.784 if blo < bhi:
2025-07-02 06:41:16.784 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.784 else:
2025-07-02 06:41:16.784 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.784 elif blo < bhi:
2025-07-02 06:41:16.784 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 > yield from g
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.784 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.784 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.784 alo = 117, ahi = 1101
2025-07-02 06:41:16.785 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.785 blo = 117, bhi = 1101
2025-07-02 06:41:16.785
2025-07-02 06:41:16.785 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.785 r"""
2025-07-02 06:41:16.785 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.785 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.785 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.785 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.785
2025-07-02 06:41:16.785 Example:
2025-07-02 06:41:16.785
2025-07-02 06:41:16.785 >>> d = Differ()
2025-07-02 06:41:16.785 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.785 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.785 >>> print(''.join(results), end="")
2025-07-02 06:41:16.785 - abcDefghiJkl
2025-07-02 06:41:16.785 + abcdefGhijkl
2025-07-02 06:41:16.786 """
2025-07-02 06:41:16.786
2025-07-02 06:41:16.786 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.786 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.786 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.786 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.786 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.786
2025-07-02 06:41:16.786 # search for the pair that matches best without being identical
2025-07-02 06:41:16.786 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.786 # on junk -- unless we have to)
2025-07-02 06:41:16.786 for j in range(blo, bhi):
2025-07-02 06:41:16.786 bj = b[j]
2025-07-02 06:41:16.786 cruncher.set_seq2(bj)
2025-07-02 06:41:16.786 for i in range(alo, ahi):
2025-07-02 06:41:16.786 ai = a[i]
2025-07-02 06:41:16.786 if ai == bj:
2025-07-02 06:41:16.786 if eqi is None:
2025-07-02 06:41:16.786 eqi, eqj = i, j
2025-07-02 06:41:16.786 continue
2025-07-02 06:41:16.786 cruncher.set_seq1(ai)
2025-07-02 06:41:16.787 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.787 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.787 # compares by a factor of 3.
2025-07-02 06:41:16.787 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.787 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.787 # of the computation is cached by cruncher
2025-07-02 06:41:16.787 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.787 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.787 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.787 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.787 if best_ratio < cutoff:
2025-07-02 06:41:16.787 # no non-identical "pretty close" pair
2025-07-02 06:41:16.787 if eqi is None:
2025-07-02 06:41:16.787 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.787 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.787 return
2025-07-02 06:41:16.787 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.787 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.787 else:
2025-07-02 06:41:16.787 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.788 eqi = None
2025-07-02 06:41:16.788
2025-07-02 06:41:16.788 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.788 # identical
2025-07-02 06:41:16.788
2025-07-02 06:41:16.788 # pump out diffs from before the synch point
2025-07-02 06:41:16.788 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.788
2025-07-02 06:41:16.788 # do intraline marking on the synch pair
2025-07-02 06:41:16.788 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.788 if eqi is None:
2025-07-02 06:41:16.788 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.788 atags = btags = ""
2025-07-02 06:41:16.788 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.788 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.788 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.788 if tag == 'replace':
2025-07-02 06:41:16.788 atags += '^' * la
2025-07-02 06:41:16.788 btags += '^' * lb
2025-07-02 06:41:16.788 elif tag == 'delete':
2025-07-02 06:41:16.789 atags += '-' * la
2025-07-02 06:41:16.789 elif tag == 'insert':
2025-07-02 06:41:16.789 btags += '+' * lb
2025-07-02 06:41:16.789 elif tag == 'equal':
2025-07-02 06:41:16.789 atags += ' ' * la
2025-07-02 06:41:16.789 btags += ' ' * lb
2025-07-02 06:41:16.789 else:
2025-07-02 06:41:16.789 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.789 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.789 else:
2025-07-02 06:41:16.789 # the synch pair is identical
2025-07-02 06:41:16.789 yield ' ' + aelt
2025-07-02 06:41:16.789
2025-07-02 06:41:16.789 # pump out diffs from after the synch point
2025-07-02 06:41:16.789 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.789
2025-07-02 06:41:16.789 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.789 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.790
2025-07-02 06:41:16.790 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.790 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.790 alo = 118, ahi = 1101
2025-07-02 06:41:16.790 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.790 blo = 118, bhi = 1101
2025-07-02 06:41:16.790
2025-07-02 06:41:16.790 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.790 g = []
2025-07-02 06:41:16.790 if alo < ahi:
2025-07-02 06:41:16.790 if blo < bhi:
2025-07-02 06:41:16.790 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.790 else:
2025-07-02 06:41:16.790 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.790 elif blo < bhi:
2025-07-02 06:41:16.790 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.790
2025-07-02 06:41:16.790 > yield from g
2025-07-02 06:41:16.790
2025-07-02 06:41:16.791 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.791 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.791 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.791 alo = 118, ahi = 1101
2025-07-02 06:41:16.791 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.791 blo = 118, bhi = 1101
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.791 r"""
2025-07-02 06:41:16.791 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.791 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.791 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.791 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791 Example:
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791 >>> d = Differ()
2025-07-02 06:41:16.791 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.792 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.792 >>> print(''.join(results), end="")
2025-07-02 06:41:16.792 - abcDefghiJkl
2025-07-02 06:41:16.792 + abcdefGhijkl
2025-07-02 06:41:16.792 """
2025-07-02 06:41:16.792
2025-07-02 06:41:16.792 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.792 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.792 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.792 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.792 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.792
2025-07-02 06:41:16.792 # search for the pair that matches best without being identical
2025-07-02 06:41:16.792 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.792 # on junk -- unless we have to)
2025-07-02 06:41:16.792 for j in range(blo, bhi):
2025-07-02 06:41:16.792 bj = b[j]
2025-07-02 06:41:16.792 cruncher.set_seq2(bj)
2025-07-02 06:41:16.792 for i in range(alo, ahi):
2025-07-02 06:41:16.793 ai = a[i]
2025-07-02 06:41:16.793 if ai == bj:
2025-07-02 06:41:16.793 if eqi is None:
2025-07-02 06:41:16.793 eqi, eqj = i, j
2025-07-02 06:41:16.793 continue
2025-07-02 06:41:16.793 cruncher.set_seq1(ai)
2025-07-02 06:41:16.793 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.793 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.793 # compares by a factor of 3.
2025-07-02 06:41:16.793 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.793 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.793 # of the computation is cached by cruncher
2025-07-02 06:41:16.793 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.793 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.793 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.793 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.793 if best_ratio < cutoff:
2025-07-02 06:41:16.794 # no non-identical "pretty close" pair
2025-07-02 06:41:16.794 if eqi is None:
2025-07-02 06:41:16.794 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.794 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.794 return
2025-07-02 06:41:16.794 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.794 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.794 else:
2025-07-02 06:41:16.794 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.794 eqi = None
2025-07-02 06:41:16.794
2025-07-02 06:41:16.794 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.794 # identical
2025-07-02 06:41:16.794
2025-07-02 06:41:16.794 # pump out diffs from before the synch point
2025-07-02 06:41:16.794 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.794
2025-07-02 06:41:16.794 # do intraline marking on the synch pair
2025-07-02 06:41:16.794 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.794 if eqi is None:
2025-07-02 06:41:16.795 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.795 atags = btags = ""
2025-07-02 06:41:16.795 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.795 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.795 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.795 if tag == 'replace':
2025-07-02 06:41:16.795 atags += '^' * la
2025-07-02 06:41:16.795 btags += '^' * lb
2025-07-02 06:41:16.795 elif tag == 'delete':
2025-07-02 06:41:16.795 atags += '-' * la
2025-07-02 06:41:16.795 elif tag == 'insert':
2025-07-02 06:41:16.795 btags += '+' * lb
2025-07-02 06:41:16.795 elif tag == 'equal':
2025-07-02 06:41:16.795 atags += ' ' * la
2025-07-02 06:41:16.795 btags += ' ' * lb
2025-07-02 06:41:16.795 else:
2025-07-02 06:41:16.795 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.795 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.795 else:
2025-07-02 06:41:16.795 # the synch pair is identical
2025-07-02 06:41:16.796 yield ' ' + aelt
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796 # pump out diffs from after the synch point
2025-07-02 06:41:16.796 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.796 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.796 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.796 alo = 119, ahi = 1101
2025-07-02 06:41:16.796 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.796 blo = 119, bhi = 1101
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.796 g = []
2025-07-02 06:41:16.796 if alo < ahi:
2025-07-02 06:41:16.796 if blo < bhi:
2025-07-02 06:41:16.796 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.796 else:
2025-07-02 06:41:16.797 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.797 elif blo < bhi:
2025-07-02 06:41:16.797 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 > yield from g
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.797 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.797 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.797 alo = 119, ahi = 1101
2025-07-02 06:41:16.797 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.797 blo = 119, bhi = 1101
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.797 r"""
2025-07-02 06:41:16.797 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.797 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.798 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.798 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.798
2025-07-02 06:41:16.798 Example:
2025-07-02 06:41:16.798
2025-07-02 06:41:16.798 >>> d = Differ()
2025-07-02 06:41:16.798 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.798 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.798 >>> print(''.join(results), end="")
2025-07-02 06:41:16.798 - abcDefghiJkl
2025-07-02 06:41:16.798 + abcdefGhijkl
2025-07-02 06:41:16.798 """
2025-07-02 06:41:16.798
2025-07-02 06:41:16.798 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.798 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.798 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.798 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.799 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.799
2025-07-02 06:41:16.799 # search for the pair that matches best without being identical
2025-07-02 06:41:16.799 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.799 # on junk -- unless we have to)
2025-07-02 06:41:16.799 for j in range(blo, bhi):
2025-07-02 06:41:16.799 bj = b[j]
2025-07-02 06:41:16.799 cruncher.set_seq2(bj)
2025-07-02 06:41:16.799 for i in range(alo, ahi):
2025-07-02 06:41:16.799 ai = a[i]
2025-07-02 06:41:16.799 if ai == bj:
2025-07-02 06:41:16.799 if eqi is None:
2025-07-02 06:41:16.799 eqi, eqj = i, j
2025-07-02 06:41:16.799 continue
2025-07-02 06:41:16.799 cruncher.set_seq1(ai)
2025-07-02 06:41:16.799 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.799 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.799 # compares by a factor of 3.
2025-07-02 06:41:16.799 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.800 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.800 # of the computation is cached by cruncher
2025-07-02 06:41:16.800 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.800 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.800 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.800 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.800 if best_ratio < cutoff:
2025-07-02 06:41:16.800 # no non-identical "pretty close" pair
2025-07-02 06:41:16.800 if eqi is None:
2025-07-02 06:41:16.800 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.800 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.800 return
2025-07-02 06:41:16.800 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.800 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.800 else:
2025-07-02 06:41:16.800 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.800 eqi = None
2025-07-02 06:41:16.800
2025-07-02 06:41:16.800 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.801 # identical
2025-07-02 06:41:16.801
2025-07-02 06:41:16.801 # pump out diffs from before the synch point
2025-07-02 06:41:16.801 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.801
2025-07-02 06:41:16.801 # do intraline marking on the synch pair
2025-07-02 06:41:16.801 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.801 if eqi is None:
2025-07-02 06:41:16.801 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.801 atags = btags = ""
2025-07-02 06:41:16.801 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.801 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.801 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.801 if tag == 'replace':
2025-07-02 06:41:16.801 atags += '^' * la
2025-07-02 06:41:16.801 btags += '^' * lb
2025-07-02 06:41:16.801 elif tag == 'delete':
2025-07-02 06:41:16.801 atags += '-' * la
2025-07-02 06:41:16.801 elif tag == 'insert':
2025-07-02 06:41:16.801 btags += '+' * lb
2025-07-02 06:41:16.801 elif tag == 'equal':
2025-07-02 06:41:16.802 atags += ' ' * la
2025-07-02 06:41:16.802 btags += ' ' * lb
2025-07-02 06:41:16.802 else:
2025-07-02 06:41:16.802 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.802 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.802 else:
2025-07-02 06:41:16.802 # the synch pair is identical
2025-07-02 06:41:16.802 yield ' ' + aelt
2025-07-02 06:41:16.802
2025-07-02 06:41:16.802 # pump out diffs from after the synch point
2025-07-02 06:41:16.802 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.802
2025-07-02 06:41:16.802 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.802 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.802
2025-07-02 06:41:16.802 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.802 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.802 alo = 120, ahi = 1101
2025-07-02 06:41:16.802 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.803 blo = 120, bhi = 1101
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.803 g = []
2025-07-02 06:41:16.803 if alo < ahi:
2025-07-02 06:41:16.803 if blo < bhi:
2025-07-02 06:41:16.803 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.803 else:
2025-07-02 06:41:16.803 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.803 elif blo < bhi:
2025-07-02 06:41:16.803 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 > yield from g
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.803 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.803 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.803 alo = 120, ahi = 1101
2025-07-02 06:41:16.803 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.804 blo = 120, bhi = 1101
2025-07-02 06:41:16.804
2025-07-02 06:41:16.804 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.804 r"""
2025-07-02 06:41:16.804 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.804 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.804 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.804 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.804
2025-07-02 06:41:16.804 Example:
2025-07-02 06:41:16.804
2025-07-02 06:41:16.804 >>> d = Differ()
2025-07-02 06:41:16.804 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.804 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.804 >>> print(''.join(results), end="")
2025-07-02 06:41:16.804 - abcDefghiJkl
2025-07-02 06:41:16.804 + abcdefGhijkl
2025-07-02 06:41:16.804 """
2025-07-02 06:41:16.805
2025-07-02 06:41:16.805 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.805 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.805 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.805 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.805 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.805
2025-07-02 06:41:16.805 # search for the pair that matches best without being identical
2025-07-02 06:41:16.805 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.805 # on junk -- unless we have to)
2025-07-02 06:41:16.805 for j in range(blo, bhi):
2025-07-02 06:41:16.805 bj = b[j]
2025-07-02 06:41:16.805 cruncher.set_seq2(bj)
2025-07-02 06:41:16.805 for i in range(alo, ahi):
2025-07-02 06:41:16.805 ai = a[i]
2025-07-02 06:41:16.805 if ai == bj:
2025-07-02 06:41:16.805 if eqi is None:
2025-07-02 06:41:16.805 eqi, eqj = i, j
2025-07-02 06:41:16.805 continue
2025-07-02 06:41:16.805 cruncher.set_seq1(ai)
2025-07-02 06:41:16.805 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.806 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.806 # compares by a factor of 3.
2025-07-02 06:41:16.806 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.806 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.806 # of the computation is cached by cruncher
2025-07-02 06:41:16.806 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.806 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.806 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.806 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.806 if best_ratio < cutoff:
2025-07-02 06:41:16.806 # no non-identical "pretty close" pair
2025-07-02 06:41:16.806 if eqi is None:
2025-07-02 06:41:16.806 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.806 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.806 return
2025-07-02 06:41:16.806 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.806 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.806 else:
2025-07-02 06:41:16.807 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.807 eqi = None
2025-07-02 06:41:16.807
2025-07-02 06:41:16.807 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.807 # identical
2025-07-02 06:41:16.807
2025-07-02 06:41:16.807 # pump out diffs from before the synch point
2025-07-02 06:41:16.807 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.807
2025-07-02 06:41:16.807 # do intraline marking on the synch pair
2025-07-02 06:41:16.807 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.807 if eqi is None:
2025-07-02 06:41:16.807 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.807 atags = btags = ""
2025-07-02 06:41:16.807 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.807 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.807 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.807 if tag == 'replace':
2025-07-02 06:41:16.807 atags += '^' * la
2025-07-02 06:41:16.808 btags += '^' * lb
2025-07-02 06:41:16.808 elif tag == 'delete':
2025-07-02 06:41:16.808 atags += '-' * la
2025-07-02 06:41:16.808 elif tag == 'insert':
2025-07-02 06:41:16.808 btags += '+' * lb
2025-07-02 06:41:16.808 elif tag == 'equal':
2025-07-02 06:41:16.808 atags += ' ' * la
2025-07-02 06:41:16.808 btags += ' ' * lb
2025-07-02 06:41:16.808 else:
2025-07-02 06:41:16.808 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.808 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.808 else:
2025-07-02 06:41:16.808 # the synch pair is identical
2025-07-02 06:41:16.808 yield ' ' + aelt
2025-07-02 06:41:16.808
2025-07-02 06:41:16.808 # pump out diffs from after the synch point
2025-07-02 06:41:16.808 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.808
2025-07-02 06:41:16.808 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.809 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.809
2025-07-02 06:41:16.809 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.809 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.809 alo = 121, ahi = 1101
2025-07-02 06:41:16.809 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.809 blo = 121, bhi = 1101
2025-07-02 06:41:16.809
2025-07-02 06:41:16.809 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.809 g = []
2025-07-02 06:41:16.809 if alo < ahi:
2025-07-02 06:41:16.809 if blo < bhi:
2025-07-02 06:41:16.809 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.809 else:
2025-07-02 06:41:16.809 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.809 elif blo < bhi:
2025-07-02 06:41:16.809 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.809
2025-07-02 06:41:16.809 > yield from g
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.810 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.810 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.810 alo = 121, ahi = 1101
2025-07-02 06:41:16.810 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.810 blo = 121, bhi = 1101
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.810 r"""
2025-07-02 06:41:16.810 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.810 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.810 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.810 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810 Example:
2025-07-02 06:41:16.811
2025-07-02 06:41:16.811 >>> d = Differ()
2025-07-02 06:41:16.811 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.811 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.811 >>> print(''.join(results), end="")
2025-07-02 06:41:16.811 - abcDefghiJkl
2025-07-02 06:41:16.811 + abcdefGhijkl
2025-07-02 06:41:16.811 """
2025-07-02 06:41:16.811
2025-07-02 06:41:16.811 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.811 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.811 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.811 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.811 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.811
2025-07-02 06:41:16.811 # search for the pair that matches best without being identical
2025-07-02 06:41:16.811 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.811 # on junk -- unless we have to)
2025-07-02 06:41:16.812 for j in range(blo, bhi):
2025-07-02 06:41:16.812 bj = b[j]
2025-07-02 06:41:16.812 cruncher.set_seq2(bj)
2025-07-02 06:41:16.812 for i in range(alo, ahi):
2025-07-02 06:41:16.812 ai = a[i]
2025-07-02 06:41:16.812 if ai == bj:
2025-07-02 06:41:16.812 if eqi is None:
2025-07-02 06:41:16.812 eqi, eqj = i, j
2025-07-02 06:41:16.812 continue
2025-07-02 06:41:16.812 cruncher.set_seq1(ai)
2025-07-02 06:41:16.812 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.812 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.812 # compares by a factor of 3.
2025-07-02 06:41:16.812 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.812 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.812 # of the computation is cached by cruncher
2025-07-02 06:41:16.812 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.812 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.812 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.813 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.813 if best_ratio < cutoff:
2025-07-02 06:41:16.813 # no non-identical "pretty close" pair
2025-07-02 06:41:16.813 if eqi is None:
2025-07-02 06:41:16.813 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.813 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.813 return
2025-07-02 06:41:16.813 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.813 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.813 else:
2025-07-02 06:41:16.813 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.813 eqi = None
2025-07-02 06:41:16.813
2025-07-02 06:41:16.813 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.813 # identical
2025-07-02 06:41:16.813
2025-07-02 06:41:16.813 # pump out diffs from before the synch point
2025-07-02 06:41:16.813 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.813
2025-07-02 06:41:16.813 # do intraline marking on the synch pair
2025-07-02 06:41:16.814 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.814 if eqi is None:
2025-07-02 06:41:16.814 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.814 atags = btags = ""
2025-07-02 06:41:16.814 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.814 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.814 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.814 if tag == 'replace':
2025-07-02 06:41:16.814 atags += '^' * la
2025-07-02 06:41:16.814 btags += '^' * lb
2025-07-02 06:41:16.814 elif tag == 'delete':
2025-07-02 06:41:16.814 atags += '-' * la
2025-07-02 06:41:16.814 elif tag == 'insert':
2025-07-02 06:41:16.814 btags += '+' * lb
2025-07-02 06:41:16.814 elif tag == 'equal':
2025-07-02 06:41:16.814 atags += ' ' * la
2025-07-02 06:41:16.814 btags += ' ' * lb
2025-07-02 06:41:16.814 else:
2025-07-02 06:41:16.814 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.814 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.815 else:
2025-07-02 06:41:16.815 # the synch pair is identical
2025-07-02 06:41:16.815 yield ' ' + aelt
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815 # pump out diffs from after the synch point
2025-07-02 06:41:16.815 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.815 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.815 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.815 alo = 122, ahi = 1101
2025-07-02 06:41:16.815 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.815 blo = 122, bhi = 1101
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.815 g = []
2025-07-02 06:41:16.815 if alo < ahi:
2025-07-02 06:41:16.816 if blo < bhi:
2025-07-02 06:41:16.816 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.816 else:
2025-07-02 06:41:16.816 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.816 elif blo < bhi:
2025-07-02 06:41:16.816 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 > yield from g
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.816 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.816 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.816 alo = 122, ahi = 1101
2025-07-02 06:41:16.816 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.816 blo = 122, bhi = 1101
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.817 r"""
2025-07-02 06:41:16.817 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.817 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.817 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.817 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.817
2025-07-02 06:41:16.817 Example:
2025-07-02 06:41:16.817
2025-07-02 06:41:16.817 >>> d = Differ()
2025-07-02 06:41:16.817 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.817 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.817 >>> print(''.join(results), end="")
2025-07-02 06:41:16.817 - abcDefghiJkl
2025-07-02 06:41:16.817 + abcdefGhijkl
2025-07-02 06:41:16.817 """
2025-07-02 06:41:16.817
2025-07-02 06:41:16.817 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.818 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.818 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.818 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.818 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.818
2025-07-02 06:41:16.818 # search for the pair that matches best without being identical
2025-07-02 06:41:16.818 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.818 # on junk -- unless we have to)
2025-07-02 06:41:16.818 for j in range(blo, bhi):
2025-07-02 06:41:16.818 bj = b[j]
2025-07-02 06:41:16.818 cruncher.set_seq2(bj)
2025-07-02 06:41:16.818 for i in range(alo, ahi):
2025-07-02 06:41:16.818 ai = a[i]
2025-07-02 06:41:16.818 if ai == bj:
2025-07-02 06:41:16.818 if eqi is None:
2025-07-02 06:41:16.818 eqi, eqj = i, j
2025-07-02 06:41:16.818 continue
2025-07-02 06:41:16.818 cruncher.set_seq1(ai)
2025-07-02 06:41:16.818 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.818 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.818 # compares by a factor of 3.
2025-07-02 06:41:16.819 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.819 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.819 # of the computation is cached by cruncher
2025-07-02 06:41:16.819 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.819 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.819 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.819 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.819 if best_ratio < cutoff:
2025-07-02 06:41:16.819 # no non-identical "pretty close" pair
2025-07-02 06:41:16.819 if eqi is None:
2025-07-02 06:41:16.819 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.819 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.819 return
2025-07-02 06:41:16.819 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.819 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.819 else:
2025-07-02 06:41:16.819 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.819 eqi = None
2025-07-02 06:41:16.819
2025-07-02 06:41:16.819 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.820 # identical
2025-07-02 06:41:16.820
2025-07-02 06:41:16.820 # pump out diffs from before the synch point
2025-07-02 06:41:16.820 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.820
2025-07-02 06:41:16.820 # do intraline marking on the synch pair
2025-07-02 06:41:16.820 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.820 if eqi is None:
2025-07-02 06:41:16.820 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.820 atags = btags = ""
2025-07-02 06:41:16.820 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.820 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.820 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.820 if tag == 'replace':
2025-07-02 06:41:16.820 atags += '^' * la
2025-07-02 06:41:16.820 btags += '^' * lb
2025-07-02 06:41:16.820 elif tag == 'delete':
2025-07-02 06:41:16.820 atags += '-' * la
2025-07-02 06:41:16.820 elif tag == 'insert':
2025-07-02 06:41:16.820 btags += '+' * lb
2025-07-02 06:41:16.821 elif tag == 'equal':
2025-07-02 06:41:16.821 atags += ' ' * la
2025-07-02 06:41:16.821 btags += ' ' * lb
2025-07-02 06:41:16.821 else:
2025-07-02 06:41:16.821 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.821 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.821 else:
2025-07-02 06:41:16.821 # the synch pair is identical
2025-07-02 06:41:16.821 yield ' ' + aelt
2025-07-02 06:41:16.821
2025-07-02 06:41:16.821 # pump out diffs from after the synch point
2025-07-02 06:41:16.821 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.821
2025-07-02 06:41:16.821 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.821 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.821
2025-07-02 06:41:16.821 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.821 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.821 alo = 123, ahi = 1101
2025-07-02 06:41:16.821 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.822 blo = 123, bhi = 1101
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.822 g = []
2025-07-02 06:41:16.822 if alo < ahi:
2025-07-02 06:41:16.822 if blo < bhi:
2025-07-02 06:41:16.822 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.822 else:
2025-07-02 06:41:16.822 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.822 elif blo < bhi:
2025-07-02 06:41:16.822 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 > yield from g
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.822 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.823 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.823 alo = 123, ahi = 1101
2025-07-02 06:41:16.823 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.823 blo = 123, bhi = 1101
2025-07-02 06:41:16.823
2025-07-02 06:41:16.823 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.823 r"""
2025-07-02 06:41:16.823 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.823 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.823 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.823 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.823
2025-07-02 06:41:16.823 Example:
2025-07-02 06:41:16.823
2025-07-02 06:41:16.823 >>> d = Differ()
2025-07-02 06:41:16.823 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.823 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.823 >>> print(''.join(results), end="")
2025-07-02 06:41:16.824 - abcDefghiJkl
2025-07-02 06:41:16.824 + abcdefGhijkl
2025-07-02 06:41:16.824 """
2025-07-02 06:41:16.824
2025-07-02 06:41:16.824 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.824 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.824 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.824 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.824 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.824
2025-07-02 06:41:16.824 # search for the pair that matches best without being identical
2025-07-02 06:41:16.824 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.824 # on junk -- unless we have to)
2025-07-02 06:41:16.824 for j in range(blo, bhi):
2025-07-02 06:41:16.824 bj = b[j]
2025-07-02 06:41:16.824 cruncher.set_seq2(bj)
2025-07-02 06:41:16.825 for i in range(alo, ahi):
2025-07-02 06:41:16.825 ai = a[i]
2025-07-02 06:41:16.825 if ai == bj:
2025-07-02 06:41:16.825 if eqi is None:
2025-07-02 06:41:16.825 eqi, eqj = i, j
2025-07-02 06:41:16.825 continue
2025-07-02 06:41:16.825 cruncher.set_seq1(ai)
2025-07-02 06:41:16.825 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.825 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.825 # compares by a factor of 3.
2025-07-02 06:41:16.825 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.825 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.825 # of the computation is cached by cruncher
2025-07-02 06:41:16.825 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.825 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.825 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.825 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.825 if best_ratio < cutoff:
2025-07-02 06:41:16.825 # no non-identical "pretty close" pair
2025-07-02 06:41:16.826 if eqi is None:
2025-07-02 06:41:16.826 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.826 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.826 return
2025-07-02 06:41:16.826 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.826 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.826 else:
2025-07-02 06:41:16.826 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.826 eqi = None
2025-07-02 06:41:16.826
2025-07-02 06:41:16.826 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.826 # identical
2025-07-02 06:41:16.826
2025-07-02 06:41:16.826 # pump out diffs from before the synch point
2025-07-02 06:41:16.826 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.826
2025-07-02 06:41:16.826 # do intraline marking on the synch pair
2025-07-02 06:41:16.826 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.826 if eqi is None:
2025-07-02 06:41:16.826 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.827 atags = btags = ""
2025-07-02 06:41:16.827 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.827 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.827 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.827 if tag == 'replace':
2025-07-02 06:41:16.827 atags += '^' * la
2025-07-02 06:41:16.827 btags += '^' * lb
2025-07-02 06:41:16.827 elif tag == 'delete':
2025-07-02 06:41:16.827 atags += '-' * la
2025-07-02 06:41:16.827 elif tag == 'insert':
2025-07-02 06:41:16.827 btags += '+' * lb
2025-07-02 06:41:16.827 elif tag == 'equal':
2025-07-02 06:41:16.827 atags += ' ' * la
2025-07-02 06:41:16.827 btags += ' ' * lb
2025-07-02 06:41:16.827 else:
2025-07-02 06:41:16.827 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.827 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.827 else:
2025-07-02 06:41:16.827 # the synch pair is identical
2025-07-02 06:41:16.827 yield ' ' + aelt
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828 # pump out diffs from after the synch point
2025-07-02 06:41:16.828 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.828 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.828 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.828 alo = 124, ahi = 1101
2025-07-02 06:41:16.828 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.828 blo = 124, bhi = 1101
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.828 g = []
2025-07-02 06:41:16.828 if alo < ahi:
2025-07-02 06:41:16.828 if blo < bhi:
2025-07-02 06:41:16.828 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.828 else:
2025-07-02 06:41:16.829 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.829 elif blo < bhi:
2025-07-02 06:41:16.829 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 > yield from g
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.829 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.829 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.829 alo = 124, ahi = 1101
2025-07-02 06:41:16.829 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.829 blo = 124, bhi = 1101
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.829 r"""
2025-07-02 06:41:16.829 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.829 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.829 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.830 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.830
2025-07-02 06:41:16.830 Example:
2025-07-02 06:41:16.830
2025-07-02 06:41:16.830 >>> d = Differ()
2025-07-02 06:41:16.830 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.830 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.830 >>> print(''.join(results), end="")
2025-07-02 06:41:16.830 - abcDefghiJkl
2025-07-02 06:41:16.830 + abcdefGhijkl
2025-07-02 06:41:16.830 """
2025-07-02 06:41:16.830
2025-07-02 06:41:16.830 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.830 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.830 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.830 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.830 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.830
2025-07-02 06:41:16.831 # search for the pair that matches best without being identical
2025-07-02 06:41:16.831 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.831 # on junk -- unless we have to)
2025-07-02 06:41:16.831 for j in range(blo, bhi):
2025-07-02 06:41:16.831 bj = b[j]
2025-07-02 06:41:16.831 cruncher.set_seq2(bj)
2025-07-02 06:41:16.831 for i in range(alo, ahi):
2025-07-02 06:41:16.831 ai = a[i]
2025-07-02 06:41:16.831 if ai == bj:
2025-07-02 06:41:16.831 if eqi is None:
2025-07-02 06:41:16.831 eqi, eqj = i, j
2025-07-02 06:41:16.831 continue
2025-07-02 06:41:16.831 cruncher.set_seq1(ai)
2025-07-02 06:41:16.831 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.831 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.831 # compares by a factor of 3.
2025-07-02 06:41:16.831 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.831 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.831 # of the computation is cached by cruncher
2025-07-02 06:41:16.831 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.832 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.832 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.832 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.832 if best_ratio < cutoff:
2025-07-02 06:41:16.832 # no non-identical "pretty close" pair
2025-07-02 06:41:16.832 if eqi is None:
2025-07-02 06:41:16.832 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.832 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.832 return
2025-07-02 06:41:16.832 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.832 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.832 else:
2025-07-02 06:41:16.832 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.832 eqi = None
2025-07-02 06:41:16.832
2025-07-02 06:41:16.832 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.832 # identical
2025-07-02 06:41:16.832
2025-07-02 06:41:16.832 # pump out diffs from before the synch point
2025-07-02 06:41:16.832 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.833
2025-07-02 06:41:16.833 # do intraline marking on the synch pair
2025-07-02 06:41:16.833 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.833 if eqi is None:
2025-07-02 06:41:16.833 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.833 atags = btags = ""
2025-07-02 06:41:16.833 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.833 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.833 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.833 if tag == 'replace':
2025-07-02 06:41:16.833 atags += '^' * la
2025-07-02 06:41:16.833 btags += '^' * lb
2025-07-02 06:41:16.833 elif tag == 'delete':
2025-07-02 06:41:16.833 atags += '-' * la
2025-07-02 06:41:16.833 elif tag == 'insert':
2025-07-02 06:41:16.833 btags += '+' * lb
2025-07-02 06:41:16.833 elif tag == 'equal':
2025-07-02 06:41:16.833 atags += ' ' * la
2025-07-02 06:41:16.834 btags += ' ' * lb
2025-07-02 06:41:16.834 else:
2025-07-02 06:41:16.834 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.834 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.834 else:
2025-07-02 06:41:16.834 # the synch pair is identical
2025-07-02 06:41:16.834 yield ' ' + aelt
2025-07-02 06:41:16.834
2025-07-02 06:41:16.834 # pump out diffs from after the synch point
2025-07-02 06:41:16.834 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.834
2025-07-02 06:41:16.834 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.834 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.834
2025-07-02 06:41:16.834 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.834 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.834 alo = 125, ahi = 1101
2025-07-02 06:41:16.834 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.834 blo = 125, bhi = 1101
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.835 g = []
2025-07-02 06:41:16.835 if alo < ahi:
2025-07-02 06:41:16.835 if blo < bhi:
2025-07-02 06:41:16.835 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.835 else:
2025-07-02 06:41:16.835 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.835 elif blo < bhi:
2025-07-02 06:41:16.835 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 > yield from g
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.835 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.835 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.835 alo = 125, ahi = 1101
2025-07-02 06:41:16.835 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.836 blo = 125, bhi = 1101
2025-07-02 06:41:16.836
2025-07-02 06:41:16.836 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.836 r"""
2025-07-02 06:41:16.836 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.836 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.836 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.836 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.836
2025-07-02 06:41:16.836 Example:
2025-07-02 06:41:16.836
2025-07-02 06:41:16.836 >>> d = Differ()
2025-07-02 06:41:16.836 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.836 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.836 >>> print(''.join(results), end="")
2025-07-02 06:41:16.836 - abcDefghiJkl
2025-07-02 06:41:16.836 + abcdefGhijkl
2025-07-02 06:41:16.837 """
2025-07-02 06:41:16.837
2025-07-02 06:41:16.837 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.837 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.837 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.837 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.837 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.837
2025-07-02 06:41:16.837 # search for the pair that matches best without being identical
2025-07-02 06:41:16.837 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.837 # on junk -- unless we have to)
2025-07-02 06:41:16.837 for j in range(blo, bhi):
2025-07-02 06:41:16.837 bj = b[j]
2025-07-02 06:41:16.837 cruncher.set_seq2(bj)
2025-07-02 06:41:16.837 for i in range(alo, ahi):
2025-07-02 06:41:16.837 ai = a[i]
2025-07-02 06:41:16.837 if ai == bj:
2025-07-02 06:41:16.837 if eqi is None:
2025-07-02 06:41:16.837 eqi, eqj = i, j
2025-07-02 06:41:16.837 continue
2025-07-02 06:41:16.837 cruncher.set_seq1(ai)
2025-07-02 06:41:16.838 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.838 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.838 # compares by a factor of 3.
2025-07-02 06:41:16.838 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.838 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.838 # of the computation is cached by cruncher
2025-07-02 06:41:16.838 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.838 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.838 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.838 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.838 if best_ratio < cutoff:
2025-07-02 06:41:16.838 # no non-identical "pretty close" pair
2025-07-02 06:41:16.838 if eqi is None:
2025-07-02 06:41:16.838 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.838 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.838 return
2025-07-02 06:41:16.838 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.838 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.838 else:
2025-07-02 06:41:16.838 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.839 eqi = None
2025-07-02 06:41:16.839
2025-07-02 06:41:16.839 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.839 # identical
2025-07-02 06:41:16.839
2025-07-02 06:41:16.839 # pump out diffs from before the synch point
2025-07-02 06:41:16.839 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.839
2025-07-02 06:41:16.839 # do intraline marking on the synch pair
2025-07-02 06:41:16.839 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.839 if eqi is None:
2025-07-02 06:41:16.839 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.839 atags = btags = ""
2025-07-02 06:41:16.839 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.839 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.839 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.839 if tag == 'replace':
2025-07-02 06:41:16.840 atags += '^' * la
2025-07-02 06:41:16.840 btags += '^' * lb
2025-07-02 06:41:16.840 elif tag == 'delete':
2025-07-02 06:41:16.840 atags += '-' * la
2025-07-02 06:41:16.840 elif tag == 'insert':
2025-07-02 06:41:16.840 btags += '+' * lb
2025-07-02 06:41:16.840 elif tag == 'equal':
2025-07-02 06:41:16.840 atags += ' ' * la
2025-07-02 06:41:16.840 btags += ' ' * lb
2025-07-02 06:41:16.840 else:
2025-07-02 06:41:16.840 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.840 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.840 else:
2025-07-02 06:41:16.840 # the synch pair is identical
2025-07-02 06:41:16.840 yield ' ' + aelt
2025-07-02 06:41:16.840
2025-07-02 06:41:16.840 # pump out diffs from after the synch point
2025-07-02 06:41:16.840 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.840
2025-07-02 06:41:16.840 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.840 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.841 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.841 alo = 126, ahi = 1101
2025-07-02 06:41:16.841 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.841 blo = 126, bhi = 1101
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.841 g = []
2025-07-02 06:41:16.841 if alo < ahi:
2025-07-02 06:41:16.841 if blo < bhi:
2025-07-02 06:41:16.841 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.841 else:
2025-07-02 06:41:16.841 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.841 elif blo < bhi:
2025-07-02 06:41:16.841 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 > yield from g
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.842 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.842 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.842 alo = 126, ahi = 1101
2025-07-02 06:41:16.842 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.842 blo = 126, bhi = 1101
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.842 r"""
2025-07-02 06:41:16.842 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.842 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.842 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.842 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842 Example:
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842 >>> d = Differ()
2025-07-02 06:41:16.843 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.843 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.843 >>> print(''.join(results), end="")
2025-07-02 06:41:16.843 - abcDefghiJkl
2025-07-02 06:41:16.843 + abcdefGhijkl
2025-07-02 06:41:16.843 """
2025-07-02 06:41:16.843
2025-07-02 06:41:16.843 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.843 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.843 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.843 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.843 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.843
2025-07-02 06:41:16.843 # search for the pair that matches best without being identical
2025-07-02 06:41:16.843 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.843 # on junk -- unless we have to)
2025-07-02 06:41:16.843 for j in range(blo, bhi):
2025-07-02 06:41:16.844 bj = b[j]
2025-07-02 06:41:16.844 cruncher.set_seq2(bj)
2025-07-02 06:41:16.844 for i in range(alo, ahi):
2025-07-02 06:41:16.844 ai = a[i]
2025-07-02 06:41:16.844 if ai == bj:
2025-07-02 06:41:16.844 if eqi is None:
2025-07-02 06:41:16.844 eqi, eqj = i, j
2025-07-02 06:41:16.844 continue
2025-07-02 06:41:16.844 cruncher.set_seq1(ai)
2025-07-02 06:41:16.844 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.844 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.844 # compares by a factor of 3.
2025-07-02 06:41:16.844 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.844 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.844 # of the computation is cached by cruncher
2025-07-02 06:41:16.844 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.844 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.844 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.844 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.844 if best_ratio < cutoff:
2025-07-02 06:41:16.845 # no non-identical "pretty close" pair
2025-07-02 06:41:16.845 if eqi is None:
2025-07-02 06:41:16.845 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.845 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.845 return
2025-07-02 06:41:16.845 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.845 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.845 else:
2025-07-02 06:41:16.845 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.845 eqi = None
2025-07-02 06:41:16.845
2025-07-02 06:41:16.845 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.845 # identical
2025-07-02 06:41:16.845
2025-07-02 06:41:16.845 # pump out diffs from before the synch point
2025-07-02 06:41:16.845 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.845
2025-07-02 06:41:16.845 # do intraline marking on the synch pair
2025-07-02 06:41:16.845 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.845 if eqi is None:
2025-07-02 06:41:16.845 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.846 atags = btags = ""
2025-07-02 06:41:16.846 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.846 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.846 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.846 if tag == 'replace':
2025-07-02 06:41:16.846 atags += '^' * la
2025-07-02 06:41:16.846 btags += '^' * lb
2025-07-02 06:41:16.846 elif tag == 'delete':
2025-07-02 06:41:16.846 atags += '-' * la
2025-07-02 06:41:16.846 elif tag == 'insert':
2025-07-02 06:41:16.846 btags += '+' * lb
2025-07-02 06:41:16.846 elif tag == 'equal':
2025-07-02 06:41:16.846 atags += ' ' * la
2025-07-02 06:41:16.846 btags += ' ' * lb
2025-07-02 06:41:16.846 else:
2025-07-02 06:41:16.846 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.846 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.846 else:
2025-07-02 06:41:16.846 # the synch pair is identical
2025-07-02 06:41:16.846 yield ' ' + aelt
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847 # pump out diffs from after the synch point
2025-07-02 06:41:16.847 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.847 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.847 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.847 alo = 127, ahi = 1101
2025-07-02 06:41:16.847 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.847 blo = 127, bhi = 1101
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.847 g = []
2025-07-02 06:41:16.847 if alo < ahi:
2025-07-02 06:41:16.847 if blo < bhi:
2025-07-02 06:41:16.847 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.847 else:
2025-07-02 06:41:16.847 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.847 elif blo < bhi:
2025-07-02 06:41:16.848 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 > yield from g
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.848 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.848 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.848 alo = 127, ahi = 1101
2025-07-02 06:41:16.848 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.848 blo = 127, bhi = 1101
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.848 r"""
2025-07-02 06:41:16.848 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.848 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.848 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.848 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.848
2025-07-02 06:41:16.849 Example:
2025-07-02 06:41:16.849
2025-07-02 06:41:16.849 >>> d = Differ()
2025-07-02 06:41:16.849 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.849 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.849 >>> print(''.join(results), end="")
2025-07-02 06:41:16.849 - abcDefghiJkl
2025-07-02 06:41:16.849 + abcdefGhijkl
2025-07-02 06:41:16.849 """
2025-07-02 06:41:16.849
2025-07-02 06:41:16.849 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.849 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.849 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.849 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.849 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.849
2025-07-02 06:41:16.849 # search for the pair that matches best without being identical
2025-07-02 06:41:16.849 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.850 # on junk -- unless we have to)
2025-07-02 06:41:16.850 for j in range(blo, bhi):
2025-07-02 06:41:16.850 bj = b[j]
2025-07-02 06:41:16.850 cruncher.set_seq2(bj)
2025-07-02 06:41:16.850 for i in range(alo, ahi):
2025-07-02 06:41:16.850 ai = a[i]
2025-07-02 06:41:16.850 if ai == bj:
2025-07-02 06:41:16.850 if eqi is None:
2025-07-02 06:41:16.850 eqi, eqj = i, j
2025-07-02 06:41:16.850 continue
2025-07-02 06:41:16.850 cruncher.set_seq1(ai)
2025-07-02 06:41:16.850 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.850 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.850 # compares by a factor of 3.
2025-07-02 06:41:16.850 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.850 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.850 # of the computation is cached by cruncher
2025-07-02 06:41:16.850 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.850 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.850 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.851 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.851 if best_ratio < cutoff:
2025-07-02 06:41:16.851 # no non-identical "pretty close" pair
2025-07-02 06:41:16.851 if eqi is None:
2025-07-02 06:41:16.851 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.851 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.851 return
2025-07-02 06:41:16.851 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.851 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.851 else:
2025-07-02 06:41:16.851 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.851 eqi = None
2025-07-02 06:41:16.851
2025-07-02 06:41:16.851 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.851 # identical
2025-07-02 06:41:16.851
2025-07-02 06:41:16.851 # pump out diffs from before the synch point
2025-07-02 06:41:16.851 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.852
2025-07-02 06:41:16.852 # do intraline marking on the synch pair
2025-07-02 06:41:16.852 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.852 if eqi is None:
2025-07-02 06:41:16.852 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.852 atags = btags = ""
2025-07-02 06:41:16.852 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.852 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.852 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.852 if tag == 'replace':
2025-07-02 06:41:16.852 atags += '^' * la
2025-07-02 06:41:16.852 btags += '^' * lb
2025-07-02 06:41:16.852 elif tag == 'delete':
2025-07-02 06:41:16.852 atags += '-' * la
2025-07-02 06:41:16.852 elif tag == 'insert':
2025-07-02 06:41:16.852 btags += '+' * lb
2025-07-02 06:41:16.852 elif tag == 'equal':
2025-07-02 06:41:16.852 atags += ' ' * la
2025-07-02 06:41:16.852 btags += ' ' * lb
2025-07-02 06:41:16.852 else:
2025-07-02 06:41:16.853 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.853 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.853 else:
2025-07-02 06:41:16.853 # the synch pair is identical
2025-07-02 06:41:16.853 yield ' ' + aelt
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853 # pump out diffs from after the synch point
2025-07-02 06:41:16.853 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.853 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.853 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.853 alo = 128, ahi = 1101
2025-07-02 06:41:16.853 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.853 blo = 128, bhi = 1101
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.853 g = []
2025-07-02 06:41:16.854 if alo < ahi:
2025-07-02 06:41:16.854 if blo < bhi:
2025-07-02 06:41:16.854 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.854 else:
2025-07-02 06:41:16.854 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.854 elif blo < bhi:
2025-07-02 06:41:16.854 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 > yield from g
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.854 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.854 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.854 alo = 128, ahi = 1101
2025-07-02 06:41:16.854 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.854 blo = 128, bhi = 1101
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.854 r"""
2025-07-02 06:41:16.855 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.855 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.855 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.855 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.855
2025-07-02 06:41:16.855 Example:
2025-07-02 06:41:16.855
2025-07-02 06:41:16.855 >>> d = Differ()
2025-07-02 06:41:16.855 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.855 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.855 >>> print(''.join(results), end="")
2025-07-02 06:41:16.855 - abcDefghiJkl
2025-07-02 06:41:16.855 + abcdefGhijkl
2025-07-02 06:41:16.855 """
2025-07-02 06:41:16.855
2025-07-02 06:41:16.855 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.856 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.856 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.856 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.856 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.856
2025-07-02 06:41:16.856 # search for the pair that matches best without being identical
2025-07-02 06:41:16.856 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.856 # on junk -- unless we have to)
2025-07-02 06:41:16.856 for j in range(blo, bhi):
2025-07-02 06:41:16.856 bj = b[j]
2025-07-02 06:41:16.856 cruncher.set_seq2(bj)
2025-07-02 06:41:16.856 for i in range(alo, ahi):
2025-07-02 06:41:16.856 ai = a[i]
2025-07-02 06:41:16.856 if ai == bj:
2025-07-02 06:41:16.856 if eqi is None:
2025-07-02 06:41:16.856 eqi, eqj = i, j
2025-07-02 06:41:16.856 continue
2025-07-02 06:41:16.856 cruncher.set_seq1(ai)
2025-07-02 06:41:16.856 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.857 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.857 # compares by a factor of 3.
2025-07-02 06:41:16.857 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.857 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.857 # of the computation is cached by cruncher
2025-07-02 06:41:16.857 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.857 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.857 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.857 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.857 if best_ratio < cutoff:
2025-07-02 06:41:16.857 # no non-identical "pretty close" pair
2025-07-02 06:41:16.857 if eqi is None:
2025-07-02 06:41:16.857 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.857 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.857 return
2025-07-02 06:41:16.857 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.857 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.857 else:
2025-07-02 06:41:16.857 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.858 eqi = None
2025-07-02 06:41:16.858
2025-07-02 06:41:16.858 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.858 # identical
2025-07-02 06:41:16.858
2025-07-02 06:41:16.858 # pump out diffs from before the synch point
2025-07-02 06:41:16.858 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.858
2025-07-02 06:41:16.858 # do intraline marking on the synch pair
2025-07-02 06:41:16.858 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.858 if eqi is None:
2025-07-02 06:41:16.858 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.858 atags = btags = ""
2025-07-02 06:41:16.858 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.858 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.858 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.858 if tag == 'replace':
2025-07-02 06:41:16.858 atags += '^' * la
2025-07-02 06:41:16.858 btags += '^' * lb
2025-07-02 06:41:16.858 elif tag == 'delete':
2025-07-02 06:41:16.859 atags += '-' * la
2025-07-02 06:41:16.859 elif tag == 'insert':
2025-07-02 06:41:16.859 btags += '+' * lb
2025-07-02 06:41:16.859 elif tag == 'equal':
2025-07-02 06:41:16.859 atags += ' ' * la
2025-07-02 06:41:16.859 btags += ' ' * lb
2025-07-02 06:41:16.859 else:
2025-07-02 06:41:16.859 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.859 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.859 else:
2025-07-02 06:41:16.859 # the synch pair is identical
2025-07-02 06:41:16.859 yield ' ' + aelt
2025-07-02 06:41:16.859
2025-07-02 06:41:16.859 # pump out diffs from after the synch point
2025-07-02 06:41:16.859 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.859
2025-07-02 06:41:16.859 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.859 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.859
2025-07-02 06:41:16.860 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.860 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.860 alo = 129, ahi = 1101
2025-07-02 06:41:16.860 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.860 blo = 129, bhi = 1101
2025-07-02 06:41:16.860
2025-07-02 06:41:16.860 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.860 g = []
2025-07-02 06:41:16.860 if alo < ahi:
2025-07-02 06:41:16.860 if blo < bhi:
2025-07-02 06:41:16.860 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.860 else:
2025-07-02 06:41:16.860 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.860 elif blo < bhi:
2025-07-02 06:41:16.860 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.860
2025-07-02 06:41:16.860 > yield from g
2025-07-02 06:41:16.860
2025-07-02 06:41:16.860 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.861 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.861 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.861 alo = 129, ahi = 1101
2025-07-02 06:41:16.861 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.861 blo = 129, bhi = 1101
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.861 r"""
2025-07-02 06:41:16.861 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.861 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.861 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.861 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861 Example:
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861 >>> d = Differ()
2025-07-02 06:41:16.862 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.862 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.862 >>> print(''.join(results), end="")
2025-07-02 06:41:16.862 - abcDefghiJkl
2025-07-02 06:41:16.862 + abcdefGhijkl
2025-07-02 06:41:16.862 """
2025-07-02 06:41:16.862
2025-07-02 06:41:16.862 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.862 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.862 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.862 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.862 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.862
2025-07-02 06:41:16.862 # search for the pair that matches best without being identical
2025-07-02 06:41:16.862 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.862 # on junk -- unless we have to)
2025-07-02 06:41:16.862 for j in range(blo, bhi):
2025-07-02 06:41:16.862 bj = b[j]
2025-07-02 06:41:16.863 cruncher.set_seq2(bj)
2025-07-02 06:41:16.863 for i in range(alo, ahi):
2025-07-02 06:41:16.863 ai = a[i]
2025-07-02 06:41:16.863 if ai == bj:
2025-07-02 06:41:16.863 if eqi is None:
2025-07-02 06:41:16.863 eqi, eqj = i, j
2025-07-02 06:41:16.863 continue
2025-07-02 06:41:16.863 cruncher.set_seq1(ai)
2025-07-02 06:41:16.863 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.863 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.863 # compares by a factor of 3.
2025-07-02 06:41:16.863 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.863 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.863 # of the computation is cached by cruncher
2025-07-02 06:41:16.863 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.863 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.863 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.863 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.863 if best_ratio < cutoff:
2025-07-02 06:41:16.864 # no non-identical "pretty close" pair
2025-07-02 06:41:16.864 if eqi is None:
2025-07-02 06:41:16.864 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.864 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.864 return
2025-07-02 06:41:16.864 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.864 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.864 else:
2025-07-02 06:41:16.864 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.864 eqi = None
2025-07-02 06:41:16.864
2025-07-02 06:41:16.864 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.864 # identical
2025-07-02 06:41:16.864
2025-07-02 06:41:16.864 # pump out diffs from before the synch point
2025-07-02 06:41:16.864 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.864
2025-07-02 06:41:16.864 # do intraline marking on the synch pair
2025-07-02 06:41:16.864 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.864 if eqi is None:
2025-07-02 06:41:16.865 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.865 atags = btags = ""
2025-07-02 06:41:16.865 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.865 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.865 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.865 if tag == 'replace':
2025-07-02 06:41:16.865 atags += '^' * la
2025-07-02 06:41:16.865 btags += '^' * lb
2025-07-02 06:41:16.865 elif tag == 'delete':
2025-07-02 06:41:16.865 atags += '-' * la
2025-07-02 06:41:16.865 elif tag == 'insert':
2025-07-02 06:41:16.865 btags += '+' * lb
2025-07-02 06:41:16.865 elif tag == 'equal':
2025-07-02 06:41:16.865 atags += ' ' * la
2025-07-02 06:41:16.865 btags += ' ' * lb
2025-07-02 06:41:16.865 else:
2025-07-02 06:41:16.865 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.865 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.865 else:
2025-07-02 06:41:16.865 # the synch pair is identical
2025-07-02 06:41:16.866 yield ' ' + aelt
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866 # pump out diffs from after the synch point
2025-07-02 06:41:16.866 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.866 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.866 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.866 alo = 130, ahi = 1101
2025-07-02 06:41:16.866 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.866 blo = 130, bhi = 1101
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.866 g = []
2025-07-02 06:41:16.866 if alo < ahi:
2025-07-02 06:41:16.866 if blo < bhi:
2025-07-02 06:41:16.866 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.867 else:
2025-07-02 06:41:16.867 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.867 elif blo < bhi:
2025-07-02 06:41:16.867 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 > yield from g
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.867 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.867 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.867 alo = 130, ahi = 1101
2025-07-02 06:41:16.867 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.867 blo = 130, bhi = 1101
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.867 r"""
2025-07-02 06:41:16.867 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.868 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.868 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.868 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.868
2025-07-02 06:41:16.868 Example:
2025-07-02 06:41:16.868
2025-07-02 06:41:16.868 >>> d = Differ()
2025-07-02 06:41:16.868 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.868 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.868 >>> print(''.join(results), end="")
2025-07-02 06:41:16.868 - abcDefghiJkl
2025-07-02 06:41:16.868 + abcdefGhijkl
2025-07-02 06:41:16.868 """
2025-07-02 06:41:16.868
2025-07-02 06:41:16.868 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.868 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.868 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.869 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.869 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.869
2025-07-02 06:41:16.869 # search for the pair that matches best without being identical
2025-07-02 06:41:16.869 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.869 # on junk -- unless we have to)
2025-07-02 06:41:16.869 for j in range(blo, bhi):
2025-07-02 06:41:16.869 bj = b[j]
2025-07-02 06:41:16.869 cruncher.set_seq2(bj)
2025-07-02 06:41:16.869 for i in range(alo, ahi):
2025-07-02 06:41:16.869 ai = a[i]
2025-07-02 06:41:16.869 if ai == bj:
2025-07-02 06:41:16.869 if eqi is None:
2025-07-02 06:41:16.869 eqi, eqj = i, j
2025-07-02 06:41:16.869 continue
2025-07-02 06:41:16.869 cruncher.set_seq1(ai)
2025-07-02 06:41:16.869 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.869 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.870 # compares by a factor of 3.
2025-07-02 06:41:16.870 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.870 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.870 # of the computation is cached by cruncher
2025-07-02 06:41:16.870 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.870 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.870 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.870 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.870 if best_ratio < cutoff:
2025-07-02 06:41:16.870 # no non-identical "pretty close" pair
2025-07-02 06:41:16.870 if eqi is None:
2025-07-02 06:41:16.870 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.870 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.870 return
2025-07-02 06:41:16.870 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.870 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.870 else:
2025-07-02 06:41:16.870 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.870 eqi = None
2025-07-02 06:41:16.871
2025-07-02 06:41:16.871 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.871 # identical
2025-07-02 06:41:16.871
2025-07-02 06:41:16.871 # pump out diffs from before the synch point
2025-07-02 06:41:16.871 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.871
2025-07-02 06:41:16.871 # do intraline marking on the synch pair
2025-07-02 06:41:16.871 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.871 if eqi is None:
2025-07-02 06:41:16.871 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.871 atags = btags = ""
2025-07-02 06:41:16.871 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.871 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.871 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.871 if tag == 'replace':
2025-07-02 06:41:16.871 atags += '^' * la
2025-07-02 06:41:16.871 btags += '^' * lb
2025-07-02 06:41:16.871 elif tag == 'delete':
2025-07-02 06:41:16.872 atags += '-' * la
2025-07-02 06:41:16.872 elif tag == 'insert':
2025-07-02 06:41:16.872 btags += '+' * lb
2025-07-02 06:41:16.872 elif tag == 'equal':
2025-07-02 06:41:16.872 atags += ' ' * la
2025-07-02 06:41:16.872 btags += ' ' * lb
2025-07-02 06:41:16.872 else:
2025-07-02 06:41:16.872 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.872 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.872 else:
2025-07-02 06:41:16.872 # the synch pair is identical
2025-07-02 06:41:16.872 yield ' ' + aelt
2025-07-02 06:41:16.872
2025-07-02 06:41:16.872 # pump out diffs from after the synch point
2025-07-02 06:41:16.872 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.872
2025-07-02 06:41:16.872 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.872 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.872
2025-07-02 06:41:16.873 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.873 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.873 alo = 131, ahi = 1101
2025-07-02 06:41:16.873 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.873 blo = 131, bhi = 1101
2025-07-02 06:41:16.873
2025-07-02 06:41:16.873 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.873 g = []
2025-07-02 06:41:16.873 if alo < ahi:
2025-07-02 06:41:16.873 if blo < bhi:
2025-07-02 06:41:16.873 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.873 else:
2025-07-02 06:41:16.873 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.873 elif blo < bhi:
2025-07-02 06:41:16.873 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.873
2025-07-02 06:41:16.873 > yield from g
2025-07-02 06:41:16.873
2025-07-02 06:41:16.873 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.873 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.874 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.874 alo = 131, ahi = 1101
2025-07-02 06:41:16.874 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.874 blo = 131, bhi = 1101
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.874 r"""
2025-07-02 06:41:16.874 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.874 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.874 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.874 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874 Example:
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874 >>> d = Differ()
2025-07-02 06:41:16.874 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.874 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.875 >>> print(''.join(results), end="")
2025-07-02 06:41:16.875 - abcDefghiJkl
2025-07-02 06:41:16.875 + abcdefGhijkl
2025-07-02 06:41:16.875 """
2025-07-02 06:41:16.875
2025-07-02 06:41:16.875 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.875 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.875 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.875 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.875 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.875
2025-07-02 06:41:16.875 # search for the pair that matches best without being identical
2025-07-02 06:41:16.875 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.875 # on junk -- unless we have to)
2025-07-02 06:41:16.875 for j in range(blo, bhi):
2025-07-02 06:41:16.875 bj = b[j]
2025-07-02 06:41:16.875 cruncher.set_seq2(bj)
2025-07-02 06:41:16.875 for i in range(alo, ahi):
2025-07-02 06:41:16.876 ai = a[i]
2025-07-02 06:41:16.876 if ai == bj:
2025-07-02 06:41:16.876 if eqi is None:
2025-07-02 06:41:16.876 eqi, eqj = i, j
2025-07-02 06:41:16.876 continue
2025-07-02 06:41:16.876 cruncher.set_seq1(ai)
2025-07-02 06:41:16.876 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.876 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.876 # compares by a factor of 3.
2025-07-02 06:41:16.876 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.876 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.876 # of the computation is cached by cruncher
2025-07-02 06:41:16.876 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.876 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.876 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.876 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.876 if best_ratio < cutoff:
2025-07-02 06:41:16.876 # no non-identical "pretty close" pair
2025-07-02 06:41:16.876 if eqi is None:
2025-07-02 06:41:16.877 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.877 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.877 return
2025-07-02 06:41:16.877 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.877 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.877 else:
2025-07-02 06:41:16.877 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.877 eqi = None
2025-07-02 06:41:16.877
2025-07-02 06:41:16.877 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.877 # identical
2025-07-02 06:41:16.877
2025-07-02 06:41:16.877 # pump out diffs from before the synch point
2025-07-02 06:41:16.877 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.877
2025-07-02 06:41:16.877 # do intraline marking on the synch pair
2025-07-02 06:41:16.877 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.877 if eqi is None:
2025-07-02 06:41:16.877 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.878 atags = btags = ""
2025-07-02 06:41:16.878 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.878 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.878 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.878 if tag == 'replace':
2025-07-02 06:41:16.878 atags += '^' * la
2025-07-02 06:41:16.878 btags += '^' * lb
2025-07-02 06:41:16.878 elif tag == 'delete':
2025-07-02 06:41:16.878 atags += '-' * la
2025-07-02 06:41:16.878 elif tag == 'insert':
2025-07-02 06:41:16.878 btags += '+' * lb
2025-07-02 06:41:16.878 elif tag == 'equal':
2025-07-02 06:41:16.878 atags += ' ' * la
2025-07-02 06:41:16.878 btags += ' ' * lb
2025-07-02 06:41:16.878 else:
2025-07-02 06:41:16.878 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.878 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.878 else:
2025-07-02 06:41:16.878 # the synch pair is identical
2025-07-02 06:41:16.879 yield ' ' + aelt
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879 # pump out diffs from after the synch point
2025-07-02 06:41:16.879 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.879 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.879 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.879 alo = 132, ahi = 1101
2025-07-02 06:41:16.879 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.879 blo = 132, bhi = 1101
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.879 g = []
2025-07-02 06:41:16.879 if alo < ahi:
2025-07-02 06:41:16.879 if blo < bhi:
2025-07-02 06:41:16.879 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.880 else:
2025-07-02 06:41:16.880 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.880 elif blo < bhi:
2025-07-02 06:41:16.880 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 > yield from g
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.880 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.880 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.880 alo = 132, ahi = 1101
2025-07-02 06:41:16.880 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.880 blo = 132, bhi = 1101
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.880 r"""
2025-07-02 06:41:16.880 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.881 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.881 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.881 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.881
2025-07-02 06:41:16.881 Example:
2025-07-02 06:41:16.881
2025-07-02 06:41:16.881 >>> d = Differ()
2025-07-02 06:41:16.881 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.881 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.881 >>> print(''.join(results), end="")
2025-07-02 06:41:16.881 - abcDefghiJkl
2025-07-02 06:41:16.881 + abcdefGhijkl
2025-07-02 06:41:16.881 """
2025-07-02 06:41:16.881
2025-07-02 06:41:16.881 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.881 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.881 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.881 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.882 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.882
2025-07-02 06:41:16.882 # search for the pair that matches best without being identical
2025-07-02 06:41:16.882 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.882 # on junk -- unless we have to)
2025-07-02 06:41:16.882 for j in range(blo, bhi):
2025-07-02 06:41:16.882 bj = b[j]
2025-07-02 06:41:16.882 cruncher.set_seq2(bj)
2025-07-02 06:41:16.882 for i in range(alo, ahi):
2025-07-02 06:41:16.882 ai = a[i]
2025-07-02 06:41:16.882 if ai == bj:
2025-07-02 06:41:16.882 if eqi is None:
2025-07-02 06:41:16.882 eqi, eqj = i, j
2025-07-02 06:41:16.882 continue
2025-07-02 06:41:16.882 cruncher.set_seq1(ai)
2025-07-02 06:41:16.882 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.882 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.882 # compares by a factor of 3.
2025-07-02 06:41:16.882 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.882 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.883 # of the computation is cached by cruncher
2025-07-02 06:41:16.883 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.883 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.883 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.883 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.883 if best_ratio < cutoff:
2025-07-02 06:41:16.883 # no non-identical "pretty close" pair
2025-07-02 06:41:16.883 if eqi is None:
2025-07-02 06:41:16.883 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.883 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.883 return
2025-07-02 06:41:16.883 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.883 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.883 else:
2025-07-02 06:41:16.883 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.883 eqi = None
2025-07-02 06:41:16.883
2025-07-02 06:41:16.883 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.883 # identical
2025-07-02 06:41:16.884
2025-07-02 06:41:16.884 # pump out diffs from before the synch point
2025-07-02 06:41:16.884 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.884
2025-07-02 06:41:16.884 # do intraline marking on the synch pair
2025-07-02 06:41:16.884 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.884 if eqi is None:
2025-07-02 06:41:16.884 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.884 atags = btags = ""
2025-07-02 06:41:16.884 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.884 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.884 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.884 if tag == 'replace':
2025-07-02 06:41:16.884 atags += '^' * la
2025-07-02 06:41:16.884 btags += '^' * lb
2025-07-02 06:41:16.884 elif tag == 'delete':
2025-07-02 06:41:16.884 atags += '-' * la
2025-07-02 06:41:16.884 elif tag == 'insert':
2025-07-02 06:41:16.884 btags += '+' * lb
2025-07-02 06:41:16.884 elif tag == 'equal':
2025-07-02 06:41:16.885 atags += ' ' * la
2025-07-02 06:41:16.885 btags += ' ' * lb
2025-07-02 06:41:16.885 else:
2025-07-02 06:41:16.885 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.885 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.885 else:
2025-07-02 06:41:16.885 # the synch pair is identical
2025-07-02 06:41:16.885 yield ' ' + aelt
2025-07-02 06:41:16.885
2025-07-02 06:41:16.885 # pump out diffs from after the synch point
2025-07-02 06:41:16.885 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.885
2025-07-02 06:41:16.885 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.885 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.885
2025-07-02 06:41:16.885 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.885 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.885 alo = 133, ahi = 1101
2025-07-02 06:41:16.885 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.886 blo = 133, bhi = 1101
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.886 g = []
2025-07-02 06:41:16.886 if alo < ahi:
2025-07-02 06:41:16.886 if blo < bhi:
2025-07-02 06:41:16.886 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.886 else:
2025-07-02 06:41:16.886 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.886 elif blo < bhi:
2025-07-02 06:41:16.886 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 > yield from g
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.886 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.886 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.887 alo = 133, ahi = 1101
2025-07-02 06:41:16.887 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.887 blo = 133, bhi = 1101
2025-07-02 06:41:16.887
2025-07-02 06:41:16.887 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.887 r"""
2025-07-02 06:41:16.887 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.887 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.887 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.887 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.887
2025-07-02 06:41:16.887 Example:
2025-07-02 06:41:16.887
2025-07-02 06:41:16.887 >>> d = Differ()
2025-07-02 06:41:16.887 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.887 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.888 >>> print(''.join(results), end="")
2025-07-02 06:41:16.888 - abcDefghiJkl
2025-07-02 06:41:16.888 + abcdefGhijkl
2025-07-02 06:41:16.888 """
2025-07-02 06:41:16.888
2025-07-02 06:41:16.888 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.888 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.888 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.888 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.888 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.888
2025-07-02 06:41:16.888 # search for the pair that matches best without being identical
2025-07-02 06:41:16.888 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.888 # on junk -- unless we have to)
2025-07-02 06:41:16.888 for j in range(blo, bhi):
2025-07-02 06:41:16.888 bj = b[j]
2025-07-02 06:41:16.888 cruncher.set_seq2(bj)
2025-07-02 06:41:16.889 for i in range(alo, ahi):
2025-07-02 06:41:16.889 ai = a[i]
2025-07-02 06:41:16.889 if ai == bj:
2025-07-02 06:41:16.889 if eqi is None:
2025-07-02 06:41:16.889 eqi, eqj = i, j
2025-07-02 06:41:16.889 continue
2025-07-02 06:41:16.889 cruncher.set_seq1(ai)
2025-07-02 06:41:16.889 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.889 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.889 # compares by a factor of 3.
2025-07-02 06:41:16.889 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.889 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.889 # of the computation is cached by cruncher
2025-07-02 06:41:16.889 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.889 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.889 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.889 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.889 if best_ratio < cutoff:
2025-07-02 06:41:16.889 # no non-identical "pretty close" pair
2025-07-02 06:41:16.890 if eqi is None:
2025-07-02 06:41:16.890 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.890 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.890 return
2025-07-02 06:41:16.890 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.890 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.890 else:
2025-07-02 06:41:16.890 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.890 eqi = None
2025-07-02 06:41:16.890
2025-07-02 06:41:16.890 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.890 # identical
2025-07-02 06:41:16.890
2025-07-02 06:41:16.890 # pump out diffs from before the synch point
2025-07-02 06:41:16.890 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.890
2025-07-02 06:41:16.890 # do intraline marking on the synch pair
2025-07-02 06:41:16.890 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.890 if eqi is None:
2025-07-02 06:41:16.891 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.891 atags = btags = ""
2025-07-02 06:41:16.891 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.891 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.891 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.891 if tag == 'replace':
2025-07-02 06:41:16.891 atags += '^' * la
2025-07-02 06:41:16.891 btags += '^' * lb
2025-07-02 06:41:16.891 elif tag == 'delete':
2025-07-02 06:41:16.891 atags += '-' * la
2025-07-02 06:41:16.891 elif tag == 'insert':
2025-07-02 06:41:16.891 btags += '+' * lb
2025-07-02 06:41:16.891 elif tag == 'equal':
2025-07-02 06:41:16.891 atags += ' ' * la
2025-07-02 06:41:16.891 btags += ' ' * lb
2025-07-02 06:41:16.891 else:
2025-07-02 06:41:16.891 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.891 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.892 else:
2025-07-02 06:41:16.892 # the synch pair is identical
2025-07-02 06:41:16.892 yield ' ' + aelt
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892 # pump out diffs from after the synch point
2025-07-02 06:41:16.892 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.892 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.892 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.892 alo = 136, ahi = 1101
2025-07-02 06:41:16.892 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.892 blo = 136, bhi = 1101
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.892 g = []
2025-07-02 06:41:16.893 if alo < ahi:
2025-07-02 06:41:16.893 if blo < bhi:
2025-07-02 06:41:16.893 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.893 else:
2025-07-02 06:41:16.893 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.893 elif blo < bhi:
2025-07-02 06:41:16.893 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.893
2025-07-02 06:41:16.893 > yield from g
2025-07-02 06:41:16.893
2025-07-02 06:41:16.893 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.893 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.893
2025-07-02 06:41:16.893 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.893 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.893 alo = 136, ahi = 1101
2025-07-02 06:41:16.893 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.893 blo = 136, bhi = 1101
2025-07-02 06:41:16.894
2025-07-02 06:41:16.894 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.894 r"""
2025-07-02 06:41:16.894 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.894 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.894 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.894 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.894
2025-07-02 06:41:16.894 Example:
2025-07-02 06:41:16.894
2025-07-02 06:41:16.894 >>> d = Differ()
2025-07-02 06:41:16.894 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.894 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.894 >>> print(''.join(results), end="")
2025-07-02 06:41:16.894 - abcDefghiJkl
2025-07-02 06:41:16.894 + abcdefGhijkl
2025-07-02 06:41:16.894 """
2025-07-02 06:41:16.895
2025-07-02 06:41:16.895 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.895 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.895 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.895 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.895 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.895
2025-07-02 06:41:16.895 # search for the pair that matches best without being identical
2025-07-02 06:41:16.895 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.895 # on junk -- unless we have to)
2025-07-02 06:41:16.895 for j in range(blo, bhi):
2025-07-02 06:41:16.895 bj = b[j]
2025-07-02 06:41:16.895 cruncher.set_seq2(bj)
2025-07-02 06:41:16.895 for i in range(alo, ahi):
2025-07-02 06:41:16.895 ai = a[i]
2025-07-02 06:41:16.895 if ai == bj:
2025-07-02 06:41:16.895 if eqi is None:
2025-07-02 06:41:16.896 eqi, eqj = i, j
2025-07-02 06:41:16.896 continue
2025-07-02 06:41:16.896 cruncher.set_seq1(ai)
2025-07-02 06:41:16.896 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.896 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.896 # compares by a factor of 3.
2025-07-02 06:41:16.896 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.896 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.896 # of the computation is cached by cruncher
2025-07-02 06:41:16.896 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.896 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.896 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.896 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.896 if best_ratio < cutoff:
2025-07-02 06:41:16.896 # no non-identical "pretty close" pair
2025-07-02 06:41:16.896 if eqi is None:
2025-07-02 06:41:16.896 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.896 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.896 return
2025-07-02 06:41:16.897 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.897 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.897 else:
2025-07-02 06:41:16.897 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.897 eqi = None
2025-07-02 06:41:16.897
2025-07-02 06:41:16.897 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.897 # identical
2025-07-02 06:41:16.897
2025-07-02 06:41:16.897 # pump out diffs from before the synch point
2025-07-02 06:41:16.897 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.897
2025-07-02 06:41:16.897 # do intraline marking on the synch pair
2025-07-02 06:41:16.897 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.897 if eqi is None:
2025-07-02 06:41:16.897 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.897 atags = btags = ""
2025-07-02 06:41:16.897 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.898 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.898 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.898 if tag == 'replace':
2025-07-02 06:41:16.898 atags += '^' * la
2025-07-02 06:41:16.898 btags += '^' * lb
2025-07-02 06:41:16.898 elif tag == 'delete':
2025-07-02 06:41:16.898 atags += '-' * la
2025-07-02 06:41:16.898 elif tag == 'insert':
2025-07-02 06:41:16.898 btags += '+' * lb
2025-07-02 06:41:16.898 elif tag == 'equal':
2025-07-02 06:41:16.898 atags += ' ' * la
2025-07-02 06:41:16.898 btags += ' ' * lb
2025-07-02 06:41:16.898 else:
2025-07-02 06:41:16.898 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.898 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.898 else:
2025-07-02 06:41:16.898 # the synch pair is identical
2025-07-02 06:41:16.898 yield ' ' + aelt
2025-07-02 06:41:16.898
2025-07-02 06:41:16.899 # pump out diffs from after the synch point
2025-07-02 06:41:16.899 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.899
2025-07-02 06:41:16.899 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.899 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.899
2025-07-02 06:41:16.899 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.899 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.899 alo = 137, ahi = 1101
2025-07-02 06:41:16.899 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.899 blo = 137, bhi = 1101
2025-07-02 06:41:16.899
2025-07-02 06:41:16.899 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.899 g = []
2025-07-02 06:41:16.899 if alo < ahi:
2025-07-02 06:41:16.899 if blo < bhi:
2025-07-02 06:41:16.899 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.900 else:
2025-07-02 06:41:16.900 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.900 elif blo < bhi:
2025-07-02 06:41:16.900 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 > yield from g
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.900 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.900 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.900 alo = 137, ahi = 1101
2025-07-02 06:41:16.900 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.900 blo = 137, bhi = 1101
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.900 r"""
2025-07-02 06:41:16.900 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.901 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.901 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.901 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.901
2025-07-02 06:41:16.901 Example:
2025-07-02 06:41:16.901
2025-07-02 06:41:16.901 >>> d = Differ()
2025-07-02 06:41:16.901 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.901 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.901 >>> print(''.join(results), end="")
2025-07-02 06:41:16.901 - abcDefghiJkl
2025-07-02 06:41:16.901 + abcdefGhijkl
2025-07-02 06:41:16.901 """
2025-07-02 06:41:16.901
2025-07-02 06:41:16.901 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.901 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.902 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.902 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.902 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.902
2025-07-02 06:41:16.902 # search for the pair that matches best without being identical
2025-07-02 06:41:16.902 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.902 # on junk -- unless we have to)
2025-07-02 06:41:16.902 for j in range(blo, bhi):
2025-07-02 06:41:16.902 bj = b[j]
2025-07-02 06:41:16.902 cruncher.set_seq2(bj)
2025-07-02 06:41:16.902 for i in range(alo, ahi):
2025-07-02 06:41:16.902 ai = a[i]
2025-07-02 06:41:16.902 if ai == bj:
2025-07-02 06:41:16.902 if eqi is None:
2025-07-02 06:41:16.902 eqi, eqj = i, j
2025-07-02 06:41:16.902 continue
2025-07-02 06:41:16.902 cruncher.set_seq1(ai)
2025-07-02 06:41:16.902 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.902 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.903 # compares by a factor of 3.
2025-07-02 06:41:16.903 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.903 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.903 # of the computation is cached by cruncher
2025-07-02 06:41:16.903 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.903 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.903 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.903 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.903 if best_ratio < cutoff:
2025-07-02 06:41:16.903 # no non-identical "pretty close" pair
2025-07-02 06:41:16.903 if eqi is None:
2025-07-02 06:41:16.903 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.903 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.903 return
2025-07-02 06:41:16.903 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.903 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.903 else:
2025-07-02 06:41:16.904 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.904 eqi = None
2025-07-02 06:41:16.904
2025-07-02 06:41:16.904 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.904 # identical
2025-07-02 06:41:16.904
2025-07-02 06:41:16.904 # pump out diffs from before the synch point
2025-07-02 06:41:16.904 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.904
2025-07-02 06:41:16.904 # do intraline marking on the synch pair
2025-07-02 06:41:16.904 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.904 if eqi is None:
2025-07-02 06:41:16.904 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.904 atags = btags = ""
2025-07-02 06:41:16.904 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.904 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.904 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.904 if tag == 'replace':
2025-07-02 06:41:16.905 atags += '^' * la
2025-07-02 06:41:16.905 btags += '^' * lb
2025-07-02 06:41:16.905 elif tag == 'delete':
2025-07-02 06:41:16.905 atags += '-' * la
2025-07-02 06:41:16.905 elif tag == 'insert':
2025-07-02 06:41:16.905 btags += '+' * lb
2025-07-02 06:41:16.905 elif tag == 'equal':
2025-07-02 06:41:16.905 atags += ' ' * la
2025-07-02 06:41:16.905 btags += ' ' * lb
2025-07-02 06:41:16.905 else:
2025-07-02 06:41:16.905 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.905 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.905 else:
2025-07-02 06:41:16.905 # the synch pair is identical
2025-07-02 06:41:16.905 yield ' ' + aelt
2025-07-02 06:41:16.905
2025-07-02 06:41:16.905 # pump out diffs from after the synch point
2025-07-02 06:41:16.905 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.906
2025-07-02 06:41:16.906 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.906 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.906
2025-07-02 06:41:16.906 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.906 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.906 alo = 138, ahi = 1101
2025-07-02 06:41:16.906 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.906 blo = 138, bhi = 1101
2025-07-02 06:41:16.906
2025-07-02 06:41:16.906 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.906 g = []
2025-07-02 06:41:16.906 if alo < ahi:
2025-07-02 06:41:16.906 if blo < bhi:
2025-07-02 06:41:16.906 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.906 else:
2025-07-02 06:41:16.906 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.906 elif blo < bhi:
2025-07-02 06:41:16.907 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 > yield from g
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.907 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.907 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.907 alo = 138, ahi = 1101
2025-07-02 06:41:16.907 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.907 blo = 138, bhi = 1101
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.907 r"""
2025-07-02 06:41:16.907 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.907 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.907 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.908 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.908
2025-07-02 06:41:16.908 Example:
2025-07-02 06:41:16.908
2025-07-02 06:41:16.908 >>> d = Differ()
2025-07-02 06:41:16.908 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.908 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.908 >>> print(''.join(results), end="")
2025-07-02 06:41:16.908 - abcDefghiJkl
2025-07-02 06:41:16.908 + abcdefGhijkl
2025-07-02 06:41:16.908 """
2025-07-02 06:41:16.908
2025-07-02 06:41:16.908 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.908 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.908 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.908 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.908 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.909
2025-07-02 06:41:16.909 # search for the pair that matches best without being identical
2025-07-02 06:41:16.909 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.909 # on junk -- unless we have to)
2025-07-02 06:41:16.909 for j in range(blo, bhi):
2025-07-02 06:41:16.909 bj = b[j]
2025-07-02 06:41:16.909 cruncher.set_seq2(bj)
2025-07-02 06:41:16.909 for i in range(alo, ahi):
2025-07-02 06:41:16.909 ai = a[i]
2025-07-02 06:41:16.909 if ai == bj:
2025-07-02 06:41:16.909 if eqi is None:
2025-07-02 06:41:16.909 eqi, eqj = i, j
2025-07-02 06:41:16.909 continue
2025-07-02 06:41:16.909 cruncher.set_seq1(ai)
2025-07-02 06:41:16.909 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.909 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.909 # compares by a factor of 3.
2025-07-02 06:41:16.909 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.909 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.910 # of the computation is cached by cruncher
2025-07-02 06:41:16.910 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.910 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.910 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.910 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.910 if best_ratio < cutoff:
2025-07-02 06:41:16.910 # no non-identical "pretty close" pair
2025-07-02 06:41:16.910 if eqi is None:
2025-07-02 06:41:16.910 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.910 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.910 return
2025-07-02 06:41:16.910 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.910 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.910 else:
2025-07-02 06:41:16.910 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.910 eqi = None
2025-07-02 06:41:16.910
2025-07-02 06:41:16.910 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.911 # identical
2025-07-02 06:41:16.911
2025-07-02 06:41:16.911 # pump out diffs from before the synch point
2025-07-02 06:41:16.911 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.911
2025-07-02 06:41:16.911 # do intraline marking on the synch pair
2025-07-02 06:41:16.911 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.911 if eqi is None:
2025-07-02 06:41:16.911 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.911 atags = btags = ""
2025-07-02 06:41:16.911 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.911 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.911 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.911 if tag == 'replace':
2025-07-02 06:41:16.911 atags += '^' * la
2025-07-02 06:41:16.911 btags += '^' * lb
2025-07-02 06:41:16.911 elif tag == 'delete':
2025-07-02 06:41:16.911 atags += '-' * la
2025-07-02 06:41:16.911 elif tag == 'insert':
2025-07-02 06:41:16.912 btags += '+' * lb
2025-07-02 06:41:16.912 elif tag == 'equal':
2025-07-02 06:41:16.912 atags += ' ' * la
2025-07-02 06:41:16.912 btags += ' ' * lb
2025-07-02 06:41:16.912 else:
2025-07-02 06:41:16.912 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.912 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.912 else:
2025-07-02 06:41:16.912 # the synch pair is identical
2025-07-02 06:41:16.912 yield ' ' + aelt
2025-07-02 06:41:16.912
2025-07-02 06:41:16.912 # pump out diffs from after the synch point
2025-07-02 06:41:16.912 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.912
2025-07-02 06:41:16.912 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.912 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.912
2025-07-02 06:41:16.912 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.912 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.913 alo = 139, ahi = 1101
2025-07-02 06:41:16.913 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.913 blo = 139, bhi = 1101
2025-07-02 06:41:16.913
2025-07-02 06:41:16.913 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.913 g = []
2025-07-02 06:41:16.913 if alo < ahi:
2025-07-02 06:41:16.913 if blo < bhi:
2025-07-02 06:41:16.913 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.913 else:
2025-07-02 06:41:16.913 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.913 elif blo < bhi:
2025-07-02 06:41:16.913 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.913
2025-07-02 06:41:16.913 > yield from g
2025-07-02 06:41:16.913
2025-07-02 06:41:16.913 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.913 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.914 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.914 alo = 139, ahi = 1101
2025-07-02 06:41:16.914 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.914 blo = 139, bhi = 1101
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.914 r"""
2025-07-02 06:41:16.914 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.914 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.914 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.914 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914 Example:
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914 >>> d = Differ()
2025-07-02 06:41:16.914 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.915 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.915 >>> print(''.join(results), end="")
2025-07-02 06:41:16.915 - abcDefghiJkl
2025-07-02 06:41:16.915 + abcdefGhijkl
2025-07-02 06:41:16.915 """
2025-07-02 06:41:16.915
2025-07-02 06:41:16.915 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.915 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.915 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.915 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.915 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.915
2025-07-02 06:41:16.915 # search for the pair that matches best without being identical
2025-07-02 06:41:16.915 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.915 # on junk -- unless we have to)
2025-07-02 06:41:16.915 for j in range(blo, bhi):
2025-07-02 06:41:16.916 bj = b[j]
2025-07-02 06:41:16.916 cruncher.set_seq2(bj)
2025-07-02 06:41:16.916 for i in range(alo, ahi):
2025-07-02 06:41:16.916 ai = a[i]
2025-07-02 06:41:16.916 if ai == bj:
2025-07-02 06:41:16.916 if eqi is None:
2025-07-02 06:41:16.916 eqi, eqj = i, j
2025-07-02 06:41:16.916 continue
2025-07-02 06:41:16.916 cruncher.set_seq1(ai)
2025-07-02 06:41:16.916 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.916 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.916 # compares by a factor of 3.
2025-07-02 06:41:16.916 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.916 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.916 # of the computation is cached by cruncher
2025-07-02 06:41:16.916 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.916 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.916 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.916 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.917 if best_ratio < cutoff:
2025-07-02 06:41:16.917 # no non-identical "pretty close" pair
2025-07-02 06:41:16.917 if eqi is None:
2025-07-02 06:41:16.917 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.917 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.917 return
2025-07-02 06:41:16.917 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.917 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.917 else:
2025-07-02 06:41:16.917 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.917 eqi = None
2025-07-02 06:41:16.917
2025-07-02 06:41:16.917 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.917 # identical
2025-07-02 06:41:16.917
2025-07-02 06:41:16.917 # pump out diffs from before the synch point
2025-07-02 06:41:16.917 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.917
2025-07-02 06:41:16.917 # do intraline marking on the synch pair
2025-07-02 06:41:16.917 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.918 if eqi is None:
2025-07-02 06:41:16.918 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.918 atags = btags = ""
2025-07-02 06:41:16.918 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.918 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.918 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.918 if tag == 'replace':
2025-07-02 06:41:16.918 atags += '^' * la
2025-07-02 06:41:16.918 btags += '^' * lb
2025-07-02 06:41:16.918 elif tag == 'delete':
2025-07-02 06:41:16.918 atags += '-' * la
2025-07-02 06:41:16.918 elif tag == 'insert':
2025-07-02 06:41:16.918 btags += '+' * lb
2025-07-02 06:41:16.918 elif tag == 'equal':
2025-07-02 06:41:16.918 atags += ' ' * la
2025-07-02 06:41:16.918 btags += ' ' * lb
2025-07-02 06:41:16.918 else:
2025-07-02 06:41:16.918 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.918 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.918 else:
2025-07-02 06:41:16.919 # the synch pair is identical
2025-07-02 06:41:16.919 yield ' ' + aelt
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919 # pump out diffs from after the synch point
2025-07-02 06:41:16.919 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.919 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.919 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.919 alo = 140, ahi = 1101
2025-07-02 06:41:16.919 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.919 blo = 140, bhi = 1101
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.919 g = []
2025-07-02 06:41:16.919 if alo < ahi:
2025-07-02 06:41:16.920 if blo < bhi:
2025-07-02 06:41:16.920 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.920 else:
2025-07-02 06:41:16.920 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.920 elif blo < bhi:
2025-07-02 06:41:16.920 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 > yield from g
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.920 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.920 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.920 alo = 140, ahi = 1101
2025-07-02 06:41:16.920 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.920 blo = 140, bhi = 1101
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.921 r"""
2025-07-02 06:41:16.921 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.921 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.921 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.921 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.921
2025-07-02 06:41:16.921 Example:
2025-07-02 06:41:16.921
2025-07-02 06:41:16.921 >>> d = Differ()
2025-07-02 06:41:16.921 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.921 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.921 >>> print(''.join(results), end="")
2025-07-02 06:41:16.921 - abcDefghiJkl
2025-07-02 06:41:16.921 + abcdefGhijkl
2025-07-02 06:41:16.921 """
2025-07-02 06:41:16.921
2025-07-02 06:41:16.921 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.922 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.922 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.922 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.922 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.922
2025-07-02 06:41:16.922 # search for the pair that matches best without being identical
2025-07-02 06:41:16.922 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.922 # on junk -- unless we have to)
2025-07-02 06:41:16.922 for j in range(blo, bhi):
2025-07-02 06:41:16.922 bj = b[j]
2025-07-02 06:41:16.922 cruncher.set_seq2(bj)
2025-07-02 06:41:16.922 for i in range(alo, ahi):
2025-07-02 06:41:16.922 ai = a[i]
2025-07-02 06:41:16.922 if ai == bj:
2025-07-02 06:41:16.922 if eqi is None:
2025-07-02 06:41:16.922 eqi, eqj = i, j
2025-07-02 06:41:16.922 continue
2025-07-02 06:41:16.922 cruncher.set_seq1(ai)
2025-07-02 06:41:16.922 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.922 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.923 # compares by a factor of 3.
2025-07-02 06:41:16.923 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.923 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.923 # of the computation is cached by cruncher
2025-07-02 06:41:16.923 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.923 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.923 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.923 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.923 if best_ratio < cutoff:
2025-07-02 06:41:16.923 # no non-identical "pretty close" pair
2025-07-02 06:41:16.923 if eqi is None:
2025-07-02 06:41:16.923 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.923 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.923 return
2025-07-02 06:41:16.923 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.923 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.923 else:
2025-07-02 06:41:16.924 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.924 eqi = None
2025-07-02 06:41:16.924
2025-07-02 06:41:16.924 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.924 # identical
2025-07-02 06:41:16.924
2025-07-02 06:41:16.924 # pump out diffs from before the synch point
2025-07-02 06:41:16.924 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.924
2025-07-02 06:41:16.924 # do intraline marking on the synch pair
2025-07-02 06:41:16.924 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.924 if eqi is None:
2025-07-02 06:41:16.924 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.924 atags = btags = ""
2025-07-02 06:41:16.924 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.924 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.924 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.924 if tag == 'replace':
2025-07-02 06:41:16.924 atags += '^' * la
2025-07-02 06:41:16.925 btags += '^' * lb
2025-07-02 06:41:16.925 elif tag == 'delete':
2025-07-02 06:41:16.925 atags += '-' * la
2025-07-02 06:41:16.925 elif tag == 'insert':
2025-07-02 06:41:16.925 btags += '+' * lb
2025-07-02 06:41:16.925 elif tag == 'equal':
2025-07-02 06:41:16.925 atags += ' ' * la
2025-07-02 06:41:16.925 btags += ' ' * lb
2025-07-02 06:41:16.925 else:
2025-07-02 06:41:16.925 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.925 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.925 else:
2025-07-02 06:41:16.925 # the synch pair is identical
2025-07-02 06:41:16.925 yield ' ' + aelt
2025-07-02 06:41:16.925
2025-07-02 06:41:16.925 # pump out diffs from after the synch point
2025-07-02 06:41:16.925 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.925
2025-07-02 06:41:16.925 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.926 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.926
2025-07-02 06:41:16.926 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.926 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.926 alo = 141, ahi = 1101
2025-07-02 06:41:16.926 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.926 blo = 141, bhi = 1101
2025-07-02 06:41:16.926
2025-07-02 06:41:16.926 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.926 g = []
2025-07-02 06:41:16.926 if alo < ahi:
2025-07-02 06:41:16.926 if blo < bhi:
2025-07-02 06:41:16.926 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.926 else:
2025-07-02 06:41:16.926 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.926 elif blo < bhi:
2025-07-02 06:41:16.926 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.926
2025-07-02 06:41:16.926 > yield from g
2025-07-02 06:41:16.926
2025-07-02 06:41:16.927 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.927 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.927 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.927 alo = 141, ahi = 1101
2025-07-02 06:41:16.927 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.927 blo = 141, bhi = 1101
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.927 r"""
2025-07-02 06:41:16.927 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.927 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.927 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.927 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927 Example:
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927 >>> d = Differ()
2025-07-02 06:41:16.928 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.928 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.928 >>> print(''.join(results), end="")
2025-07-02 06:41:16.928 - abcDefghiJkl
2025-07-02 06:41:16.928 + abcdefGhijkl
2025-07-02 06:41:16.928 """
2025-07-02 06:41:16.928
2025-07-02 06:41:16.928 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.928 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.928 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.928 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.928 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.928
2025-07-02 06:41:16.928 # search for the pair that matches best without being identical
2025-07-02 06:41:16.928 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.928 # on junk -- unless we have to)
2025-07-02 06:41:16.928 for j in range(blo, bhi):
2025-07-02 06:41:16.929 bj = b[j]
2025-07-02 06:41:16.929 cruncher.set_seq2(bj)
2025-07-02 06:41:16.929 for i in range(alo, ahi):
2025-07-02 06:41:16.929 ai = a[i]
2025-07-02 06:41:16.929 if ai == bj:
2025-07-02 06:41:16.929 if eqi is None:
2025-07-02 06:41:16.929 eqi, eqj = i, j
2025-07-02 06:41:16.929 continue
2025-07-02 06:41:16.929 cruncher.set_seq1(ai)
2025-07-02 06:41:16.929 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.929 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.929 # compares by a factor of 3.
2025-07-02 06:41:16.929 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.929 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.929 # of the computation is cached by cruncher
2025-07-02 06:41:16.929 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.929 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.929 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.929 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.929 if best_ratio < cutoff:
2025-07-02 06:41:16.930 # no non-identical "pretty close" pair
2025-07-02 06:41:16.930 if eqi is None:
2025-07-02 06:41:16.930 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.930 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.930 return
2025-07-02 06:41:16.930 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.930 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.930 else:
2025-07-02 06:41:16.930 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.930 eqi = None
2025-07-02 06:41:16.930
2025-07-02 06:41:16.930 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.930 # identical
2025-07-02 06:41:16.930
2025-07-02 06:41:16.930 # pump out diffs from before the synch point
2025-07-02 06:41:16.930 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.930
2025-07-02 06:41:16.930 # do intraline marking on the synch pair
2025-07-02 06:41:16.930 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.931 if eqi is None:
2025-07-02 06:41:16.931 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.931 atags = btags = ""
2025-07-02 06:41:16.931 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.931 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.931 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.931 if tag == 'replace':
2025-07-02 06:41:16.931 atags += '^' * la
2025-07-02 06:41:16.931 btags += '^' * lb
2025-07-02 06:41:16.931 elif tag == 'delete':
2025-07-02 06:41:16.931 atags += '-' * la
2025-07-02 06:41:16.931 elif tag == 'insert':
2025-07-02 06:41:16.931 btags += '+' * lb
2025-07-02 06:41:16.931 elif tag == 'equal':
2025-07-02 06:41:16.931 atags += ' ' * la
2025-07-02 06:41:16.931 btags += ' ' * lb
2025-07-02 06:41:16.931 else:
2025-07-02 06:41:16.931 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.931 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.931 else:
2025-07-02 06:41:16.932 # the synch pair is identical
2025-07-02 06:41:16.932 yield ' ' + aelt
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932 # pump out diffs from after the synch point
2025-07-02 06:41:16.932 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.932 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.932 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.932 alo = 142, ahi = 1101
2025-07-02 06:41:16.932 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.932 blo = 142, bhi = 1101
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.932 g = []
2025-07-02 06:41:16.932 if alo < ahi:
2025-07-02 06:41:16.933 if blo < bhi:
2025-07-02 06:41:16.933 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.933 else:
2025-07-02 06:41:16.933 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.933 elif blo < bhi:
2025-07-02 06:41:16.933 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 > yield from g
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.933 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.933 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.933 alo = 142, ahi = 1101
2025-07-02 06:41:16.933 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.933 blo = 142, bhi = 1101
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.934 r"""
2025-07-02 06:41:16.934 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.934 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.934 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.934 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.934
2025-07-02 06:41:16.934 Example:
2025-07-02 06:41:16.934
2025-07-02 06:41:16.934 >>> d = Differ()
2025-07-02 06:41:16.934 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.934 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.934 >>> print(''.join(results), end="")
2025-07-02 06:41:16.934 - abcDefghiJkl
2025-07-02 06:41:16.934 + abcdefGhijkl
2025-07-02 06:41:16.934 """
2025-07-02 06:41:16.934
2025-07-02 06:41:16.934 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.935 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.935 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.935 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.935 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.935
2025-07-02 06:41:16.935 # search for the pair that matches best without being identical
2025-07-02 06:41:16.935 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.935 # on junk -- unless we have to)
2025-07-02 06:41:16.935 for j in range(blo, bhi):
2025-07-02 06:41:16.935 bj = b[j]
2025-07-02 06:41:16.935 cruncher.set_seq2(bj)
2025-07-02 06:41:16.935 for i in range(alo, ahi):
2025-07-02 06:41:16.935 ai = a[i]
2025-07-02 06:41:16.935 if ai == bj:
2025-07-02 06:41:16.935 if eqi is None:
2025-07-02 06:41:16.935 eqi, eqj = i, j
2025-07-02 06:41:16.935 continue
2025-07-02 06:41:16.936 cruncher.set_seq1(ai)
2025-07-02 06:41:16.936 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.936 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.936 # compares by a factor of 3.
2025-07-02 06:41:16.936 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.936 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.936 # of the computation is cached by cruncher
2025-07-02 06:41:16.936 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.936 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.936 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.936 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.936 if best_ratio < cutoff:
2025-07-02 06:41:16.936 # no non-identical "pretty close" pair
2025-07-02 06:41:16.936 if eqi is None:
2025-07-02 06:41:16.936 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.936 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.936 return
2025-07-02 06:41:16.936 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.936 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.937 else:
2025-07-02 06:41:16.937 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.937 eqi = None
2025-07-02 06:41:16.937
2025-07-02 06:41:16.937 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.937 # identical
2025-07-02 06:41:16.937
2025-07-02 06:41:16.937 # pump out diffs from before the synch point
2025-07-02 06:41:16.937 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.937
2025-07-02 06:41:16.937 # do intraline marking on the synch pair
2025-07-02 06:41:16.937 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.937 if eqi is None:
2025-07-02 06:41:16.937 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.937 atags = btags = ""
2025-07-02 06:41:16.937 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.937 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.937 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.937 if tag == 'replace':
2025-07-02 06:41:16.938 atags += '^' * la
2025-07-02 06:41:16.938 btags += '^' * lb
2025-07-02 06:41:16.938 elif tag == 'delete':
2025-07-02 06:41:16.938 atags += '-' * la
2025-07-02 06:41:16.938 elif tag == 'insert':
2025-07-02 06:41:16.938 btags += '+' * lb
2025-07-02 06:41:16.938 elif tag == 'equal':
2025-07-02 06:41:16.938 atags += ' ' * la
2025-07-02 06:41:16.938 btags += ' ' * lb
2025-07-02 06:41:16.938 else:
2025-07-02 06:41:16.938 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.938 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.938 else:
2025-07-02 06:41:16.938 # the synch pair is identical
2025-07-02 06:41:16.938 yield ' ' + aelt
2025-07-02 06:41:16.938
2025-07-02 06:41:16.938 # pump out diffs from after the synch point
2025-07-02 06:41:16.938 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.938
2025-07-02 06:41:16.939 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.939 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.939
2025-07-02 06:41:16.939 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.939 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.939 alo = 143, ahi = 1101
2025-07-02 06:41:16.939 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.939 blo = 143, bhi = 1101
2025-07-02 06:41:16.939
2025-07-02 06:41:16.939 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.939 g = []
2025-07-02 06:41:16.939 if alo < ahi:
2025-07-02 06:41:16.939 if blo < bhi:
2025-07-02 06:41:16.939 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.939 else:
2025-07-02 06:41:16.939 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.939 elif blo < bhi:
2025-07-02 06:41:16.939 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.939
2025-07-02 06:41:16.940 > yield from g
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.940 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.940 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.940 alo = 143, ahi = 1101
2025-07-02 06:41:16.940 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.940 blo = 143, bhi = 1101
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.940 r"""
2025-07-02 06:41:16.940 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.940 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.940 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.940 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940 Example:
2025-07-02 06:41:16.940
2025-07-02 06:41:16.941 >>> d = Differ()
2025-07-02 06:41:16.941 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.941 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.941 >>> print(''.join(results), end="")
2025-07-02 06:41:16.941 - abcDefghiJkl
2025-07-02 06:41:16.941 + abcdefGhijkl
2025-07-02 06:41:16.941 """
2025-07-02 06:41:16.941
2025-07-02 06:41:16.941 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.941 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.941 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.941 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.941 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.941
2025-07-02 06:41:16.941 # search for the pair that matches best without being identical
2025-07-02 06:41:16.941 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.942 # on junk -- unless we have to)
2025-07-02 06:41:16.942 for j in range(blo, bhi):
2025-07-02 06:41:16.942 bj = b[j]
2025-07-02 06:41:16.942 cruncher.set_seq2(bj)
2025-07-02 06:41:16.942 for i in range(alo, ahi):
2025-07-02 06:41:16.942 ai = a[i]
2025-07-02 06:41:16.942 if ai == bj:
2025-07-02 06:41:16.942 if eqi is None:
2025-07-02 06:41:16.942 eqi, eqj = i, j
2025-07-02 06:41:16.942 continue
2025-07-02 06:41:16.942 cruncher.set_seq1(ai)
2025-07-02 06:41:16.942 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.942 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.942 # compares by a factor of 3.
2025-07-02 06:41:16.942 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.942 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.942 # of the computation is cached by cruncher
2025-07-02 06:41:16.942 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.942 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.943 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.943 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.943 if best_ratio < cutoff:
2025-07-02 06:41:16.943 # no non-identical "pretty close" pair
2025-07-02 06:41:16.943 if eqi is None:
2025-07-02 06:41:16.943 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.943 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.943 return
2025-07-02 06:41:16.943 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.943 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.943 else:
2025-07-02 06:41:16.943 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.943 eqi = None
2025-07-02 06:41:16.943
2025-07-02 06:41:16.943 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.943 # identical
2025-07-02 06:41:16.943
2025-07-02 06:41:16.943 # pump out diffs from before the synch point
2025-07-02 06:41:16.943 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.944
2025-07-02 06:41:16.944 # do intraline marking on the synch pair
2025-07-02 06:41:16.944 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.944 if eqi is None:
2025-07-02 06:41:16.944 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.944 atags = btags = ""
2025-07-02 06:41:16.944 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.944 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.944 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.944 if tag == 'replace':
2025-07-02 06:41:16.944 atags += '^' * la
2025-07-02 06:41:16.944 btags += '^' * lb
2025-07-02 06:41:16.944 elif tag == 'delete':
2025-07-02 06:41:16.944 atags += '-' * la
2025-07-02 06:41:16.944 elif tag == 'insert':
2025-07-02 06:41:16.944 btags += '+' * lb
2025-07-02 06:41:16.944 elif tag == 'equal':
2025-07-02 06:41:16.944 atags += ' ' * la
2025-07-02 06:41:16.944 btags += ' ' * lb
2025-07-02 06:41:16.944 else:
2025-07-02 06:41:16.945 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.945 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.945 else:
2025-07-02 06:41:16.945 # the synch pair is identical
2025-07-02 06:41:16.945 yield ' ' + aelt
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945 # pump out diffs from after the synch point
2025-07-02 06:41:16.945 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.945 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.945 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.945 alo = 144, ahi = 1101
2025-07-02 06:41:16.945 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.945 blo = 144, bhi = 1101
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.946 g = []
2025-07-02 06:41:16.946 if alo < ahi:
2025-07-02 06:41:16.946 if blo < bhi:
2025-07-02 06:41:16.946 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.946 else:
2025-07-02 06:41:16.946 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.946 elif blo < bhi:
2025-07-02 06:41:16.946 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.946
2025-07-02 06:41:16.946 > yield from g
2025-07-02 06:41:16.946
2025-07-02 06:41:16.946 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.946 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.946
2025-07-02 06:41:16.946 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.946 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.946 alo = 144, ahi = 1101
2025-07-02 06:41:16.946 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.946 blo = 144, bhi = 1101
2025-07-02 06:41:16.947
2025-07-02 06:41:16.947 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.947 r"""
2025-07-02 06:41:16.947 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.947 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.947 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.947 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.947
2025-07-02 06:41:16.947 Example:
2025-07-02 06:41:16.947
2025-07-02 06:41:16.947 >>> d = Differ()
2025-07-02 06:41:16.947 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.947 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.947 >>> print(''.join(results), end="")
2025-07-02 06:41:16.947 - abcDefghiJkl
2025-07-02 06:41:16.947 + abcdefGhijkl
2025-07-02 06:41:16.947 """
2025-07-02 06:41:16.947
2025-07-02 06:41:16.948 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.948 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.948 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.948 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.948 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.948
2025-07-02 06:41:16.948 # search for the pair that matches best without being identical
2025-07-02 06:41:16.948 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.948 # on junk -- unless we have to)
2025-07-02 06:41:16.948 for j in range(blo, bhi):
2025-07-02 06:41:16.948 bj = b[j]
2025-07-02 06:41:16.948 cruncher.set_seq2(bj)
2025-07-02 06:41:16.948 for i in range(alo, ahi):
2025-07-02 06:41:16.948 ai = a[i]
2025-07-02 06:41:16.948 if ai == bj:
2025-07-02 06:41:16.948 if eqi is None:
2025-07-02 06:41:16.948 eqi, eqj = i, j
2025-07-02 06:41:16.948 continue
2025-07-02 06:41:16.948 cruncher.set_seq1(ai)
2025-07-02 06:41:16.949 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.949 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.949 # compares by a factor of 3.
2025-07-02 06:41:16.949 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.949 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.949 # of the computation is cached by cruncher
2025-07-02 06:41:16.949 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.949 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.949 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.949 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.949 if best_ratio < cutoff:
2025-07-02 06:41:16.949 # no non-identical "pretty close" pair
2025-07-02 06:41:16.949 if eqi is None:
2025-07-02 06:41:16.949 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.949 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.949 return
2025-07-02 06:41:16.949 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.949 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.949 else:
2025-07-02 06:41:16.950 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.950 eqi = None
2025-07-02 06:41:16.950
2025-07-02 06:41:16.950 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.950 # identical
2025-07-02 06:41:16.950
2025-07-02 06:41:16.950 # pump out diffs from before the synch point
2025-07-02 06:41:16.950 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.950
2025-07-02 06:41:16.950 # do intraline marking on the synch pair
2025-07-02 06:41:16.950 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.950 if eqi is None:
2025-07-02 06:41:16.950 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.950 atags = btags = ""
2025-07-02 06:41:16.950 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.950 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.950 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.950 if tag == 'replace':
2025-07-02 06:41:16.950 atags += '^' * la
2025-07-02 06:41:16.951 btags += '^' * lb
2025-07-02 06:41:16.951 elif tag == 'delete':
2025-07-02 06:41:16.951 atags += '-' * la
2025-07-02 06:41:16.951 elif tag == 'insert':
2025-07-02 06:41:16.951 btags += '+' * lb
2025-07-02 06:41:16.951 elif tag == 'equal':
2025-07-02 06:41:16.951 atags += ' ' * la
2025-07-02 06:41:16.951 btags += ' ' * lb
2025-07-02 06:41:16.951 else:
2025-07-02 06:41:16.951 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.951 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.951 else:
2025-07-02 06:41:16.951 # the synch pair is identical
2025-07-02 06:41:16.951 yield ' ' + aelt
2025-07-02 06:41:16.951
2025-07-02 06:41:16.951 # pump out diffs from after the synch point
2025-07-02 06:41:16.951 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.951
2025-07-02 06:41:16.952 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.952 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.952
2025-07-02 06:41:16.952 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.952 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.952 alo = 145, ahi = 1101
2025-07-02 06:41:16.952 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.952 blo = 145, bhi = 1101
2025-07-02 06:41:16.952
2025-07-02 06:41:16.952 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.952 g = []
2025-07-02 06:41:16.952 if alo < ahi:
2025-07-02 06:41:16.952 if blo < bhi:
2025-07-02 06:41:16.952 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.952 else:
2025-07-02 06:41:16.952 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.952 elif blo < bhi:
2025-07-02 06:41:16.952 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 > yield from g
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.953 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.953 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.953 alo = 145, ahi = 1101
2025-07-02 06:41:16.953 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.953 blo = 145, bhi = 1101
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.953 r"""
2025-07-02 06:41:16.953 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.953 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.953 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.953 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.953
2025-07-02 06:41:16.954 Example:
2025-07-02 06:41:16.954
2025-07-02 06:41:16.954 >>> d = Differ()
2025-07-02 06:41:16.954 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.954 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.954 >>> print(''.join(results), end="")
2025-07-02 06:41:16.954 - abcDefghiJkl
2025-07-02 06:41:16.954 + abcdefGhijkl
2025-07-02 06:41:16.954 """
2025-07-02 06:41:16.954
2025-07-02 06:41:16.954 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.954 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.954 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.954 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.954 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.954
2025-07-02 06:41:16.954 # search for the pair that matches best without being identical
2025-07-02 06:41:16.955 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.955 # on junk -- unless we have to)
2025-07-02 06:41:16.955 for j in range(blo, bhi):
2025-07-02 06:41:16.955 bj = b[j]
2025-07-02 06:41:16.955 cruncher.set_seq2(bj)
2025-07-02 06:41:16.955 for i in range(alo, ahi):
2025-07-02 06:41:16.955 ai = a[i]
2025-07-02 06:41:16.955 if ai == bj:
2025-07-02 06:41:16.955 if eqi is None:
2025-07-02 06:41:16.955 eqi, eqj = i, j
2025-07-02 06:41:16.955 continue
2025-07-02 06:41:16.955 cruncher.set_seq1(ai)
2025-07-02 06:41:16.955 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.955 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.955 # compares by a factor of 3.
2025-07-02 06:41:16.955 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.955 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.955 # of the computation is cached by cruncher
2025-07-02 06:41:16.955 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.956 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.956 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.956 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.956 if best_ratio < cutoff:
2025-07-02 06:41:16.956 # no non-identical "pretty close" pair
2025-07-02 06:41:16.956 if eqi is None:
2025-07-02 06:41:16.956 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.956 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.956 return
2025-07-02 06:41:16.956 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.956 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.956 else:
2025-07-02 06:41:16.956 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.956 eqi = None
2025-07-02 06:41:16.956
2025-07-02 06:41:16.956 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.956 # identical
2025-07-02 06:41:16.956
2025-07-02 06:41:16.957 # pump out diffs from before the synch point
2025-07-02 06:41:16.957 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.957
2025-07-02 06:41:16.957 # do intraline marking on the synch pair
2025-07-02 06:41:16.957 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.957 if eqi is None:
2025-07-02 06:41:16.957 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.957 atags = btags = ""
2025-07-02 06:41:16.957 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.957 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.957 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.957 if tag == 'replace':
2025-07-02 06:41:16.957 atags += '^' * la
2025-07-02 06:41:16.957 btags += '^' * lb
2025-07-02 06:41:16.957 elif tag == 'delete':
2025-07-02 06:41:16.957 atags += '-' * la
2025-07-02 06:41:16.957 elif tag == 'insert':
2025-07-02 06:41:16.957 btags += '+' * lb
2025-07-02 06:41:16.957 elif tag == 'equal':
2025-07-02 06:41:16.958 atags += ' ' * la
2025-07-02 06:41:16.958 btags += ' ' * lb
2025-07-02 06:41:16.958 else:
2025-07-02 06:41:16.958 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.958 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.958 else:
2025-07-02 06:41:16.958 # the synch pair is identical
2025-07-02 06:41:16.958 yield ' ' + aelt
2025-07-02 06:41:16.958
2025-07-02 06:41:16.958 # pump out diffs from after the synch point
2025-07-02 06:41:16.958 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.958
2025-07-02 06:41:16.958 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.958 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.958
2025-07-02 06:41:16.958 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.958 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.958 alo = 146, ahi = 1101
2025-07-02 06:41:16.958 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.959 blo = 146, bhi = 1101
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.959 g = []
2025-07-02 06:41:16.959 if alo < ahi:
2025-07-02 06:41:16.959 if blo < bhi:
2025-07-02 06:41:16.959 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.959 else:
2025-07-02 06:41:16.959 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.959 elif blo < bhi:
2025-07-02 06:41:16.959 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 > yield from g
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.959 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.960 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.960 alo = 146, ahi = 1101
2025-07-02 06:41:16.960 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.960 blo = 146, bhi = 1101
2025-07-02 06:41:16.960
2025-07-02 06:41:16.960 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.960 r"""
2025-07-02 06:41:16.960 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.960 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.960 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.960 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.960
2025-07-02 06:41:16.960 Example:
2025-07-02 06:41:16.960
2025-07-02 06:41:16.960 >>> d = Differ()
2025-07-02 06:41:16.960 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.960 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.961 >>> print(''.join(results), end="")
2025-07-02 06:41:16.961 - abcDefghiJkl
2025-07-02 06:41:16.961 + abcdefGhijkl
2025-07-02 06:41:16.961 """
2025-07-02 06:41:16.961
2025-07-02 06:41:16.961 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.961 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.961 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.961 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.961 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.961
2025-07-02 06:41:16.961 # search for the pair that matches best without being identical
2025-07-02 06:41:16.961 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.961 # on junk -- unless we have to)
2025-07-02 06:41:16.961 for j in range(blo, bhi):
2025-07-02 06:41:16.961 bj = b[j]
2025-07-02 06:41:16.961 cruncher.set_seq2(bj)
2025-07-02 06:41:16.961 for i in range(alo, ahi):
2025-07-02 06:41:16.962 ai = a[i]
2025-07-02 06:41:16.962 if ai == bj:
2025-07-02 06:41:16.962 if eqi is None:
2025-07-02 06:41:16.962 eqi, eqj = i, j
2025-07-02 06:41:16.962 continue
2025-07-02 06:41:16.962 cruncher.set_seq1(ai)
2025-07-02 06:41:16.962 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.962 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.962 # compares by a factor of 3.
2025-07-02 06:41:16.962 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.962 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.962 # of the computation is cached by cruncher
2025-07-02 06:41:16.962 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.962 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.962 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.962 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.962 if best_ratio < cutoff:
2025-07-02 06:41:16.962 # no non-identical "pretty close" pair
2025-07-02 06:41:16.962 if eqi is None:
2025-07-02 06:41:16.962 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.963 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.963 return
2025-07-02 06:41:16.963 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.963 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.963 else:
2025-07-02 06:41:16.963 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.963 eqi = None
2025-07-02 06:41:16.963
2025-07-02 06:41:16.963 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.963 # identical
2025-07-02 06:41:16.963
2025-07-02 06:41:16.963 # pump out diffs from before the synch point
2025-07-02 06:41:16.963 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.963
2025-07-02 06:41:16.963 # do intraline marking on the synch pair
2025-07-02 06:41:16.963 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.963 if eqi is None:
2025-07-02 06:41:16.963 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.963 atags = btags = ""
2025-07-02 06:41:16.963 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.963 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.964 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.964 if tag == 'replace':
2025-07-02 06:41:16.964 atags += '^' * la
2025-07-02 06:41:16.964 btags += '^' * lb
2025-07-02 06:41:16.964 elif tag == 'delete':
2025-07-02 06:41:16.964 atags += '-' * la
2025-07-02 06:41:16.964 elif tag == 'insert':
2025-07-02 06:41:16.964 btags += '+' * lb
2025-07-02 06:41:16.964 elif tag == 'equal':
2025-07-02 06:41:16.964 atags += ' ' * la
2025-07-02 06:41:16.964 btags += ' ' * lb
2025-07-02 06:41:16.964 else:
2025-07-02 06:41:16.964 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.964 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.964 else:
2025-07-02 06:41:16.964 # the synch pair is identical
2025-07-02 06:41:16.964 yield ' ' + aelt
2025-07-02 06:41:16.964
2025-07-02 06:41:16.964 # pump out diffs from after the synch point
2025-07-02 06:41:16.964 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.965
2025-07-02 06:41:16.965 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.965 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.965
2025-07-02 06:41:16.965 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.965 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.965 alo = 147, ahi = 1101
2025-07-02 06:41:16.965 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.965 blo = 147, bhi = 1101
2025-07-02 06:41:16.965
2025-07-02 06:41:16.965 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.965 g = []
2025-07-02 06:41:16.965 if alo < ahi:
2025-07-02 06:41:16.965 if blo < bhi:
2025-07-02 06:41:16.965 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.965 else:
2025-07-02 06:41:16.965 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.965 elif blo < bhi:
2025-07-02 06:41:16.965 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.965
2025-07-02 06:41:16.966 > yield from g
2025-07-02 06:41:16.966
2025-07-02 06:41:16.966 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.966 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.966
2025-07-02 06:41:16.966 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.966 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.966 alo = 147, ahi = 1101
2025-07-02 06:41:16.966 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.966 blo = 147, bhi = 1101
2025-07-02 06:41:16.966
2025-07-02 06:41:16.966 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.966 r"""
2025-07-02 06:41:16.966 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.966 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.966 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.966 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.966
2025-07-02 06:41:16.967 Example:
2025-07-02 06:41:16.967
2025-07-02 06:41:16.967 >>> d = Differ()
2025-07-02 06:41:16.967 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.967 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.967 >>> print(''.join(results), end="")
2025-07-02 06:41:16.967 - abcDefghiJkl
2025-07-02 06:41:16.967 + abcdefGhijkl
2025-07-02 06:41:16.967 """
2025-07-02 06:41:16.967
2025-07-02 06:41:16.967 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.967 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.967 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.967 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.967 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.967
2025-07-02 06:41:16.967 # search for the pair that matches best without being identical
2025-07-02 06:41:16.967 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.967 # on junk -- unless we have to)
2025-07-02 06:41:16.968 for j in range(blo, bhi):
2025-07-02 06:41:16.968 bj = b[j]
2025-07-02 06:41:16.968 cruncher.set_seq2(bj)
2025-07-02 06:41:16.968 for i in range(alo, ahi):
2025-07-02 06:41:16.968 ai = a[i]
2025-07-02 06:41:16.968 if ai == bj:
2025-07-02 06:41:16.968 if eqi is None:
2025-07-02 06:41:16.968 eqi, eqj = i, j
2025-07-02 06:41:16.968 continue
2025-07-02 06:41:16.968 cruncher.set_seq1(ai)
2025-07-02 06:41:16.968 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.968 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.968 # compares by a factor of 3.
2025-07-02 06:41:16.968 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.968 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.968 # of the computation is cached by cruncher
2025-07-02 06:41:16.968 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.968 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.968 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.969 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.969 if best_ratio < cutoff:
2025-07-02 06:41:16.969 # no non-identical "pretty close" pair
2025-07-02 06:41:16.969 if eqi is None:
2025-07-02 06:41:16.969 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.969 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.969 return
2025-07-02 06:41:16.969 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.969 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.969 else:
2025-07-02 06:41:16.969 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.969 eqi = None
2025-07-02 06:41:16.969
2025-07-02 06:41:16.969 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.969 # identical
2025-07-02 06:41:16.969
2025-07-02 06:41:16.969 # pump out diffs from before the synch point
2025-07-02 06:41:16.969 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.969
2025-07-02 06:41:16.969 # do intraline marking on the synch pair
2025-07-02 06:41:16.970 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.970 if eqi is None:
2025-07-02 06:41:16.970 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.970 atags = btags = ""
2025-07-02 06:41:16.970 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.970 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.970 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.970 if tag == 'replace':
2025-07-02 06:41:16.970 atags += '^' * la
2025-07-02 06:41:16.970 btags += '^' * lb
2025-07-02 06:41:16.970 elif tag == 'delete':
2025-07-02 06:41:16.970 atags += '-' * la
2025-07-02 06:41:16.970 elif tag == 'insert':
2025-07-02 06:41:16.970 btags += '+' * lb
2025-07-02 06:41:16.970 elif tag == 'equal':
2025-07-02 06:41:16.970 atags += ' ' * la
2025-07-02 06:41:16.970 btags += ' ' * lb
2025-07-02 06:41:16.970 else:
2025-07-02 06:41:16.970 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.970 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.971 else:
2025-07-02 06:41:16.971 # the synch pair is identical
2025-07-02 06:41:16.971 yield ' ' + aelt
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971 # pump out diffs from after the synch point
2025-07-02 06:41:16.971 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.971 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.971 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.971 alo = 148, ahi = 1101
2025-07-02 06:41:16.971 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.971 blo = 148, bhi = 1101
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.971 g = []
2025-07-02 06:41:16.971 if alo < ahi:
2025-07-02 06:41:16.971 if blo < bhi:
2025-07-02 06:41:16.972 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.972 else:
2025-07-02 06:41:16.972 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.972 elif blo < bhi:
2025-07-02 06:41:16.972 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 > yield from g
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.972 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.972 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.972 alo = 148, ahi = 1101
2025-07-02 06:41:16.972 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.972 blo = 148, bhi = 1101
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.972 r"""
2025-07-02 06:41:16.972 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.973 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.973 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.973 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.973
2025-07-02 06:41:16.973 Example:
2025-07-02 06:41:16.973
2025-07-02 06:41:16.973 >>> d = Differ()
2025-07-02 06:41:16.973 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.973 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.973 >>> print(''.join(results), end="")
2025-07-02 06:41:16.973 - abcDefghiJkl
2025-07-02 06:41:16.973 + abcdefGhijkl
2025-07-02 06:41:16.973 """
2025-07-02 06:41:16.973
2025-07-02 06:41:16.973 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.973 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.973 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.973 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.973 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.974
2025-07-02 06:41:16.974 # search for the pair that matches best without being identical
2025-07-02 06:41:16.974 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.974 # on junk -- unless we have to)
2025-07-02 06:41:16.974 for j in range(blo, bhi):
2025-07-02 06:41:16.974 bj = b[j]
2025-07-02 06:41:16.974 cruncher.set_seq2(bj)
2025-07-02 06:41:16.974 for i in range(alo, ahi):
2025-07-02 06:41:16.974 ai = a[i]
2025-07-02 06:41:16.974 if ai == bj:
2025-07-02 06:41:16.974 if eqi is None:
2025-07-02 06:41:16.974 eqi, eqj = i, j
2025-07-02 06:41:16.974 continue
2025-07-02 06:41:16.974 cruncher.set_seq1(ai)
2025-07-02 06:41:16.974 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.974 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.974 # compares by a factor of 3.
2025-07-02 06:41:16.974 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.974 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.974 # of the computation is cached by cruncher
2025-07-02 06:41:16.975 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.975 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.975 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.975 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.975 if best_ratio < cutoff:
2025-07-02 06:41:16.975 # no non-identical "pretty close" pair
2025-07-02 06:41:16.975 if eqi is None:
2025-07-02 06:41:16.975 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.975 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.975 return
2025-07-02 06:41:16.975 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.975 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.975 else:
2025-07-02 06:41:16.975 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.975 eqi = None
2025-07-02 06:41:16.975
2025-07-02 06:41:16.975 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.975 # identical
2025-07-02 06:41:16.975
2025-07-02 06:41:16.975 # pump out diffs from before the synch point
2025-07-02 06:41:16.975 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.976
2025-07-02 06:41:16.976 # do intraline marking on the synch pair
2025-07-02 06:41:16.976 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.976 if eqi is None:
2025-07-02 06:41:16.976 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.976 atags = btags = ""
2025-07-02 06:41:16.976 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.976 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.976 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.976 if tag == 'replace':
2025-07-02 06:41:16.976 atags += '^' * la
2025-07-02 06:41:16.976 btags += '^' * lb
2025-07-02 06:41:16.976 elif tag == 'delete':
2025-07-02 06:41:16.976 atags += '-' * la
2025-07-02 06:41:16.976 elif tag == 'insert':
2025-07-02 06:41:16.976 btags += '+' * lb
2025-07-02 06:41:16.976 elif tag == 'equal':
2025-07-02 06:41:16.976 atags += ' ' * la
2025-07-02 06:41:16.976 btags += ' ' * lb
2025-07-02 06:41:16.976 else:
2025-07-02 06:41:16.977 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.977 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.977 else:
2025-07-02 06:41:16.977 # the synch pair is identical
2025-07-02 06:41:16.977 yield ' ' + aelt
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977 # pump out diffs from after the synch point
2025-07-02 06:41:16.977 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.977 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.977 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.977 alo = 149, ahi = 1101
2025-07-02 06:41:16.977 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.977 blo = 149, bhi = 1101
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.978 g = []
2025-07-02 06:41:16.978 if alo < ahi:
2025-07-02 06:41:16.978 if blo < bhi:
2025-07-02 06:41:16.978 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.978 else:
2025-07-02 06:41:16.978 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.978 elif blo < bhi:
2025-07-02 06:41:16.978 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.978
2025-07-02 06:41:16.978 > yield from g
2025-07-02 06:41:16.978
2025-07-02 06:41:16.978 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.978 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.978
2025-07-02 06:41:16.978 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.978 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.978 alo = 149, ahi = 1101
2025-07-02 06:41:16.978 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.978 blo = 149, bhi = 1101
2025-07-02 06:41:16.978
2025-07-02 06:41:16.979 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.979 r"""
2025-07-02 06:41:16.979 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.979 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.979 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.979 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.979
2025-07-02 06:41:16.979 Example:
2025-07-02 06:41:16.979
2025-07-02 06:41:16.979 >>> d = Differ()
2025-07-02 06:41:16.979 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.979 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.979 >>> print(''.join(results), end="")
2025-07-02 06:41:16.979 - abcDefghiJkl
2025-07-02 06:41:16.979 + abcdefGhijkl
2025-07-02 06:41:16.979 """
2025-07-02 06:41:16.979
2025-07-02 06:41:16.979 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.980 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.980 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.980 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.980 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.980
2025-07-02 06:41:16.980 # search for the pair that matches best without being identical
2025-07-02 06:41:16.980 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.980 # on junk -- unless we have to)
2025-07-02 06:41:16.980 for j in range(blo, bhi):
2025-07-02 06:41:16.980 bj = b[j]
2025-07-02 06:41:16.980 cruncher.set_seq2(bj)
2025-07-02 06:41:16.980 for i in range(alo, ahi):
2025-07-02 06:41:16.980 ai = a[i]
2025-07-02 06:41:16.980 if ai == bj:
2025-07-02 06:41:16.980 if eqi is None:
2025-07-02 06:41:16.980 eqi, eqj = i, j
2025-07-02 06:41:16.980 continue
2025-07-02 06:41:16.980 cruncher.set_seq1(ai)
2025-07-02 06:41:16.980 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.980 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.980 # compares by a factor of 3.
2025-07-02 06:41:16.981 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.981 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.981 # of the computation is cached by cruncher
2025-07-02 06:41:16.981 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.981 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.981 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.981 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.981 if best_ratio < cutoff:
2025-07-02 06:41:16.981 # no non-identical "pretty close" pair
2025-07-02 06:41:16.981 if eqi is None:
2025-07-02 06:41:16.981 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.981 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.981 return
2025-07-02 06:41:16.981 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.981 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.981 else:
2025-07-02 06:41:16.981 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.981 eqi = None
2025-07-02 06:41:16.981
2025-07-02 06:41:16.981 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.982 # identical
2025-07-02 06:41:16.982
2025-07-02 06:41:16.982 # pump out diffs from before the synch point
2025-07-02 06:41:16.982 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.982
2025-07-02 06:41:16.982 # do intraline marking on the synch pair
2025-07-02 06:41:16.982 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.982 if eqi is None:
2025-07-02 06:41:16.982 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.982 atags = btags = ""
2025-07-02 06:41:16.982 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.982 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.982 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.982 if tag == 'replace':
2025-07-02 06:41:16.982 atags += '^' * la
2025-07-02 06:41:16.982 btags += '^' * lb
2025-07-02 06:41:16.982 elif tag == 'delete':
2025-07-02 06:41:16.982 atags += '-' * la
2025-07-02 06:41:16.983 elif tag == 'insert':
2025-07-02 06:41:16.983 btags += '+' * lb
2025-07-02 06:41:16.983 elif tag == 'equal':
2025-07-02 06:41:16.983 atags += ' ' * la
2025-07-02 06:41:16.983 btags += ' ' * lb
2025-07-02 06:41:16.983 else:
2025-07-02 06:41:16.983 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.983 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.983 else:
2025-07-02 06:41:16.983 # the synch pair is identical
2025-07-02 06:41:16.983 yield ' ' + aelt
2025-07-02 06:41:16.983
2025-07-02 06:41:16.983 # pump out diffs from after the synch point
2025-07-02 06:41:16.983 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.983
2025-07-02 06:41:16.983 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.983 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.983
2025-07-02 06:41:16.983 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.983 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.984 alo = 150, ahi = 1101
2025-07-02 06:41:16.984 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.984 blo = 150, bhi = 1101
2025-07-02 06:41:16.984
2025-07-02 06:41:16.984 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.984 g = []
2025-07-02 06:41:16.984 if alo < ahi:
2025-07-02 06:41:16.984 if blo < bhi:
2025-07-02 06:41:16.984 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.984 else:
2025-07-02 06:41:16.984 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.984 elif blo < bhi:
2025-07-02 06:41:16.984 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.984
2025-07-02 06:41:16.984 > yield from g
2025-07-02 06:41:16.984
2025-07-02 06:41:16.984 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.984 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.985 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.985 alo = 150, ahi = 1101
2025-07-02 06:41:16.985 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.985 blo = 150, bhi = 1101
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.985 r"""
2025-07-02 06:41:16.985 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.985 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.985 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.985 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985 Example:
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985 >>> d = Differ()
2025-07-02 06:41:16.985 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.985 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.986 >>> print(''.join(results), end="")
2025-07-02 06:41:16.986 - abcDefghiJkl
2025-07-02 06:41:16.986 + abcdefGhijkl
2025-07-02 06:41:16.986 """
2025-07-02 06:41:16.986
2025-07-02 06:41:16.986 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.986 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.986 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.986 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.986 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.986
2025-07-02 06:41:16.986 # search for the pair that matches best without being identical
2025-07-02 06:41:16.986 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.986 # on junk -- unless we have to)
2025-07-02 06:41:16.986 for j in range(blo, bhi):
2025-07-02 06:41:16.986 bj = b[j]
2025-07-02 06:41:16.986 cruncher.set_seq2(bj)
2025-07-02 06:41:16.987 for i in range(alo, ahi):
2025-07-02 06:41:16.987 ai = a[i]
2025-07-02 06:41:16.987 if ai == bj:
2025-07-02 06:41:16.987 if eqi is None:
2025-07-02 06:41:16.987 eqi, eqj = i, j
2025-07-02 06:41:16.987 continue
2025-07-02 06:41:16.987 cruncher.set_seq1(ai)
2025-07-02 06:41:16.987 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.987 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.987 # compares by a factor of 3.
2025-07-02 06:41:16.987 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.987 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.987 # of the computation is cached by cruncher
2025-07-02 06:41:16.987 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.987 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.987 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.987 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.987 if best_ratio < cutoff:
2025-07-02 06:41:16.987 # no non-identical "pretty close" pair
2025-07-02 06:41:16.987 if eqi is None:
2025-07-02 06:41:16.988 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.988 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.988 return
2025-07-02 06:41:16.988 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.988 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.988 else:
2025-07-02 06:41:16.988 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.988 eqi = None
2025-07-02 06:41:16.988
2025-07-02 06:41:16.988 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.988 # identical
2025-07-02 06:41:16.988
2025-07-02 06:41:16.988 # pump out diffs from before the synch point
2025-07-02 06:41:16.988 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.988
2025-07-02 06:41:16.988 # do intraline marking on the synch pair
2025-07-02 06:41:16.988 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.988 if eqi is None:
2025-07-02 06:41:16.988 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.988 atags = btags = ""
2025-07-02 06:41:16.989 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.989 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.989 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.989 if tag == 'replace':
2025-07-02 06:41:16.989 atags += '^' * la
2025-07-02 06:41:16.989 btags += '^' * lb
2025-07-02 06:41:16.989 elif tag == 'delete':
2025-07-02 06:41:16.989 atags += '-' * la
2025-07-02 06:41:16.989 elif tag == 'insert':
2025-07-02 06:41:16.989 btags += '+' * lb
2025-07-02 06:41:16.989 elif tag == 'equal':
2025-07-02 06:41:16.989 atags += ' ' * la
2025-07-02 06:41:16.989 btags += ' ' * lb
2025-07-02 06:41:16.989 else:
2025-07-02 06:41:16.989 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.989 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.989 else:
2025-07-02 06:41:16.989 # the synch pair is identical
2025-07-02 06:41:16.989 yield ' ' + aelt
2025-07-02 06:41:16.989
2025-07-02 06:41:16.989 # pump out diffs from after the synch point
2025-07-02 06:41:16.990 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.990
2025-07-02 06:41:16.990 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.990 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.990
2025-07-02 06:41:16.990 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.990 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.990 alo = 151, ahi = 1101
2025-07-02 06:41:16.990 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.990 blo = 151, bhi = 1101
2025-07-02 06:41:16.990
2025-07-02 06:41:16.990 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.990 g = []
2025-07-02 06:41:16.990 if alo < ahi:
2025-07-02 06:41:16.990 if blo < bhi:
2025-07-02 06:41:16.990 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.990 else:
2025-07-02 06:41:16.990 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.990 elif blo < bhi:
2025-07-02 06:41:16.990 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 > yield from g
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.991 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.991 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.991 alo = 151, ahi = 1101
2025-07-02 06:41:16.991 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.991 blo = 151, bhi = 1101
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.991 r"""
2025-07-02 06:41:16.991 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.991 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.991 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.991 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 Example:
2025-07-02 06:41:16.992
2025-07-02 06:41:16.992 >>> d = Differ()
2025-07-02 06:41:16.992 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.992 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.992 >>> print(''.join(results), end="")
2025-07-02 06:41:16.992 - abcDefghiJkl
2025-07-02 06:41:16.992 + abcdefGhijkl
2025-07-02 06:41:16.992 """
2025-07-02 06:41:16.992
2025-07-02 06:41:16.992 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.992 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.992 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.992 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.992 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.992
2025-07-02 06:41:16.992 # search for the pair that matches best without being identical
2025-07-02 06:41:16.992 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.992 # on junk -- unless we have to)
2025-07-02 06:41:16.992 for j in range(blo, bhi):
2025-07-02 06:41:16.993 bj = b[j]
2025-07-02 06:41:16.993 cruncher.set_seq2(bj)
2025-07-02 06:41:16.993 for i in range(alo, ahi):
2025-07-02 06:41:16.993 ai = a[i]
2025-07-02 06:41:16.993 if ai == bj:
2025-07-02 06:41:16.993 if eqi is None:
2025-07-02 06:41:16.993 eqi, eqj = i, j
2025-07-02 06:41:16.993 continue
2025-07-02 06:41:16.993 cruncher.set_seq1(ai)
2025-07-02 06:41:16.993 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.993 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.993 # compares by a factor of 3.
2025-07-02 06:41:16.993 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.993 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.993 # of the computation is cached by cruncher
2025-07-02 06:41:16.993 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.993 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.993 cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.993 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.993 if best_ratio < cutoff:
2025-07-02 06:41:16.994 # no non-identical "pretty close" pair
2025-07-02 06:41:16.994 if eqi is None:
2025-07-02 06:41:16.994 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.994 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.994 return
2025-07-02 06:41:16.994 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.994 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.994 else:
2025-07-02 06:41:16.994 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.994 eqi = None
2025-07-02 06:41:16.994
2025-07-02 06:41:16.994 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.994 # identical
2025-07-02 06:41:16.994
2025-07-02 06:41:16.994 # pump out diffs from before the synch point
2025-07-02 06:41:16.994 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.994
2025-07-02 06:41:16.994 # do intraline marking on the synch pair
2025-07-02 06:41:16.994 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.995 if eqi is None:
2025-07-02 06:41:16.995 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.995 atags = btags = ""
2025-07-02 06:41:16.995 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.995 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.995 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.995 if tag == 'replace':
2025-07-02 06:41:16.995 atags += '^' * la
2025-07-02 06:41:16.995 btags += '^' * lb
2025-07-02 06:41:16.995 elif tag == 'delete':
2025-07-02 06:41:16.995 atags += '-' * la
2025-07-02 06:41:16.995 elif tag == 'insert':
2025-07-02 06:41:16.995 btags += '+' * lb
2025-07-02 06:41:16.995 elif tag == 'equal':
2025-07-02 06:41:16.995 atags += ' ' * la
2025-07-02 06:41:16.995 btags += ' ' * lb
2025-07-02 06:41:16.995 else:
2025-07-02 06:41:16.995 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.995 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.996 else:
2025-07-02 06:41:16.996 # the synch pair is identical
2025-07-02 06:41:16.996 yield ' ' + aelt
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996 # pump out diffs from after the synch point
2025-07-02 06:41:16.996 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.996 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.996 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.996 alo = 152, ahi = 1101
2025-07-02 06:41:16.996 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.996 blo = 152, bhi = 1101
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.996 g = []
2025-07-02 06:41:16.996 if alo < ahi:
2025-07-02 06:41:16.996 if blo < bhi:
2025-07-02 06:41:16.997 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.997 else:
2025-07-02 06:41:16.997 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.997 elif blo < bhi:
2025-07-02 06:41:16.997 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 > yield from g
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.997 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.997 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:16.997 alo = 152, ahi = 1101
2025-07-02 06:41:16.997 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:16.997 blo = 152, bhi = 1101
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.998 r"""
2025-07-02 06:41:16.998 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.998 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.998 synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.998 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.998
2025-07-02 06:41:16.998 Example:
2025-07-02 06:41:16.998
2025-07-02 06:41:16.998 >>> d = Differ()
2025-07-02 06:41:16.998 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.998 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.998 >>> print(''.join(results), end="")
2025-07-02 06:41:16.998 - abcDefghiJkl
2025-07-02 06:41:16.998 + abcdefGhijkl
2025-07-02 06:41:16.998 """
2025-07-02 06:41:16.998
2025-07-02 06:41:16.998 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.998 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.999 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.999 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.999 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:16.999
2025-07-02 06:41:16.999 # search for the pair that matches best without being identical
2025-07-02 06:41:16.999 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.999 # on junk -- unless we have to)
2025-07-02 06:41:16.999 for j in range(blo, bhi):
2025-07-02 06:41:16.999 bj = b[j]
2025-07-02 06:41:16.999 cruncher.set_seq2(bj)
2025-07-02 06:41:16.999 for i in range(alo, ahi):
2025-07-02 06:41:16.999 ai = a[i]
2025-07-02 06:41:16.999 if ai == bj:
2025-07-02 06:41:16.999 if eqi is None:
2025-07-02 06:41:16.999 eqi, eqj = i, j
2025-07-02 06:41:16.999 continue
2025-07-02 06:41:16.999 cruncher.set_seq1(ai)
2025-07-02 06:41:16.999 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.999 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.999 # compares by a factor of 3.
2025-07-02 06:41:17.000 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.000 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.000 # of the computation is cached by cruncher
2025-07-02 06:41:17.000 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.000 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.000 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.000 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.000 if best_ratio < cutoff:
2025-07-02 06:41:17.000 # no non-identical "pretty close" pair
2025-07-02 06:41:17.000 if eqi is None:
2025-07-02 06:41:17.000 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.000 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.000 return
2025-07-02 06:41:17.000 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.000 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.000 else:
2025-07-02 06:41:17.000 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.000 eqi = None
2025-07-02 06:41:17.000
2025-07-02 06:41:17.000 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.001 # identical
2025-07-02 06:41:17.001
2025-07-02 06:41:17.001 # pump out diffs from before the synch point
2025-07-02 06:41:17.001 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.001
2025-07-02 06:41:17.001 # do intraline marking on the synch pair
2025-07-02 06:41:17.001 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.001 if eqi is None:
2025-07-02 06:41:17.001 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.001 atags = btags = ""
2025-07-02 06:41:17.001 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.001 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.001 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.001 if tag == 'replace':
2025-07-02 06:41:17.001 atags += '^' * la
2025-07-02 06:41:17.001 btags += '^' * lb
2025-07-02 06:41:17.001 elif tag == 'delete':
2025-07-02 06:41:17.001 atags += '-' * la
2025-07-02 06:41:17.001 elif tag == 'insert':
2025-07-02 06:41:17.001 btags += '+' * lb
2025-07-02 06:41:17.002 elif tag == 'equal':
2025-07-02 06:41:17.002 atags += ' ' * la
2025-07-02 06:41:17.002 btags += ' ' * lb
2025-07-02 06:41:17.002 else:
2025-07-02 06:41:17.002 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.002 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.002 else:
2025-07-02 06:41:17.002 # the synch pair is identical
2025-07-02 06:41:17.002 yield ' ' + aelt
2025-07-02 06:41:17.002
2025-07-02 06:41:17.002 # pump out diffs from after the synch point
2025-07-02 06:41:17.002 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.002
2025-07-02 06:41:17.002 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.002 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.002
2025-07-02 06:41:17.002 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.002 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.002 alo = 153, ahi = 1101
2025-07-02 06:41:17.002 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.003 blo = 153, bhi = 1101
2025-07-02 06:41:17.003
2025-07-02 06:41:17.003 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.003 g = []
2025-07-02 06:41:17.003 if alo < ahi:
2025-07-02 06:41:17.003 if blo < bhi:
2025-07-02 06:41:17.003 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.003 else:
2025-07-02 06:41:17.003 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.003 elif blo < bhi:
2025-07-02 06:41:17.003 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.003
2025-07-02 06:41:17.003 > yield from g
2025-07-02 06:41:17.003
2025-07-02 06:41:17.003 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.003 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.003
2025-07-02 06:41:17.004 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.004 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.004 alo = 153, ahi = 1101
2025-07-02 06:41:17.004 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.004 blo = 153, bhi = 1101
2025-07-02 06:41:17.004
2025-07-02 06:41:17.004 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.004 r"""
2025-07-02 06:41:17.004 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.004 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.004 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.004 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.004
2025-07-02 06:41:17.004 Example:
2025-07-02 06:41:17.004
2025-07-02 06:41:17.004 >>> d = Differ()
2025-07-02 06:41:17.004 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.004 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.004 >>> print(''.join(results), end="")
2025-07-02 06:41:17.005 - abcDefghiJkl
2025-07-02 06:41:17.005 + abcdefGhijkl
2025-07-02 06:41:17.005 """
2025-07-02 06:41:17.005
2025-07-02 06:41:17.005 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.005 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.005 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.005 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.005 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.005
2025-07-02 06:41:17.005 # search for the pair that matches best without being identical
2025-07-02 06:41:17.005 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.005 # on junk -- unless we have to)
2025-07-02 06:41:17.005 for j in range(blo, bhi):
2025-07-02 06:41:17.005 bj = b[j]
2025-07-02 06:41:17.005 cruncher.set_seq2(bj)
2025-07-02 06:41:17.005 for i in range(alo, ahi):
2025-07-02 06:41:17.005 ai = a[i]
2025-07-02 06:41:17.006 if ai == bj:
2025-07-02 06:41:17.006 if eqi is None:
2025-07-02 06:41:17.006 eqi, eqj = i, j
2025-07-02 06:41:17.006 continue
2025-07-02 06:41:17.006 cruncher.set_seq1(ai)
2025-07-02 06:41:17.006 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.006 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.006 # compares by a factor of 3.
2025-07-02 06:41:17.006 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.006 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.006 # of the computation is cached by cruncher
2025-07-02 06:41:17.006 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.006 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.006 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.006 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.006 if best_ratio < cutoff:
2025-07-02 06:41:17.006 # no non-identical "pretty close" pair
2025-07-02 06:41:17.006 if eqi is None:
2025-07-02 06:41:17.006 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.006 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.006 return
2025-07-02 06:41:17.007 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.007 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.007 else:
2025-07-02 06:41:17.007 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.007 eqi = None
2025-07-02 06:41:17.007
2025-07-02 06:41:17.007 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.007 # identical
2025-07-02 06:41:17.007
2025-07-02 06:41:17.007 # pump out diffs from before the synch point
2025-07-02 06:41:17.007 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.007
2025-07-02 06:41:17.007 # do intraline marking on the synch pair
2025-07-02 06:41:17.007 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.007 if eqi is None:
2025-07-02 06:41:17.007 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.007 atags = btags = ""
2025-07-02 06:41:17.007 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.007 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.007 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.008 if tag == 'replace':
2025-07-02 06:41:17.008 atags += '^' * la
2025-07-02 06:41:17.008 btags += '^' * lb
2025-07-02 06:41:17.008 elif tag == 'delete':
2025-07-02 06:41:17.008 atags += '-' * la
2025-07-02 06:41:17.008 elif tag == 'insert':
2025-07-02 06:41:17.008 btags += '+' * lb
2025-07-02 06:41:17.008 elif tag == 'equal':
2025-07-02 06:41:17.008 atags += ' ' * la
2025-07-02 06:41:17.008 btags += ' ' * lb
2025-07-02 06:41:17.008 else:
2025-07-02 06:41:17.008 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.008 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.008 else:
2025-07-02 06:41:17.008 # the synch pair is identical
2025-07-02 06:41:17.008 yield ' ' + aelt
2025-07-02 06:41:17.008
2025-07-02 06:41:17.008 # pump out diffs from after the synch point
2025-07-02 06:41:17.008 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.008
2025-07-02 06:41:17.008 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.009 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.009
2025-07-02 06:41:17.009 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.009 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.009 alo = 154, ahi = 1101
2025-07-02 06:41:17.009 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.009 blo = 154, bhi = 1101
2025-07-02 06:41:17.009
2025-07-02 06:41:17.009 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.009 g = []
2025-07-02 06:41:17.009 if alo < ahi:
2025-07-02 06:41:17.009 if blo < bhi:
2025-07-02 06:41:17.009 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.009 else:
2025-07-02 06:41:17.009 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.009 elif blo < bhi:
2025-07-02 06:41:17.009 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.009
2025-07-02 06:41:17.009 > yield from g
2025-07-02 06:41:17.009
2025-07-02 06:41:17.010 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.010 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.010 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.010 alo = 154, ahi = 1101
2025-07-02 06:41:17.010 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.010 blo = 154, bhi = 1101
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.010 r"""
2025-07-02 06:41:17.010 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.010 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.010 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.010 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010 Example:
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010 >>> d = Differ()
2025-07-02 06:41:17.010 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.011 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.011 >>> print(''.join(results), end="")
2025-07-02 06:41:17.011 - abcDefghiJkl
2025-07-02 06:41:17.011 + abcdefGhijkl
2025-07-02 06:41:17.011 """
2025-07-02 06:41:17.011
2025-07-02 06:41:17.011 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.011 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.011 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.011 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.011 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.011
2025-07-02 06:41:17.011 # search for the pair that matches best without being identical
2025-07-02 06:41:17.011 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.011 # on junk -- unless we have to)
2025-07-02 06:41:17.011 for j in range(blo, bhi):
2025-07-02 06:41:17.011 bj = b[j]
2025-07-02 06:41:17.011 cruncher.set_seq2(bj)
2025-07-02 06:41:17.012 for i in range(alo, ahi):
2025-07-02 06:41:17.012 ai = a[i]
2025-07-02 06:41:17.012 if ai == bj:
2025-07-02 06:41:17.012 if eqi is None:
2025-07-02 06:41:17.012 eqi, eqj = i, j
2025-07-02 06:41:17.012 continue
2025-07-02 06:41:17.012 cruncher.set_seq1(ai)
2025-07-02 06:41:17.012 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.012 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.012 # compares by a factor of 3.
2025-07-02 06:41:17.012 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.012 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.012 # of the computation is cached by cruncher
2025-07-02 06:41:17.012 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.012 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.012 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.012 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.012 if best_ratio < cutoff:
2025-07-02 06:41:17.013 # no non-identical "pretty close" pair
2025-07-02 06:41:17.013 if eqi is None:
2025-07-02 06:41:17.013 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.013 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.013 return
2025-07-02 06:41:17.013 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.013 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.013 else:
2025-07-02 06:41:17.013 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.013 eqi = None
2025-07-02 06:41:17.013
2025-07-02 06:41:17.013 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.013 # identical
2025-07-02 06:41:17.013
2025-07-02 06:41:17.013 # pump out diffs from before the synch point
2025-07-02 06:41:17.013 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.013
2025-07-02 06:41:17.013 # do intraline marking on the synch pair
2025-07-02 06:41:17.013 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.013 if eqi is None:
2025-07-02 06:41:17.014 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.014 atags = btags = ""
2025-07-02 06:41:17.014 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.014 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.014 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.014 if tag == 'replace':
2025-07-02 06:41:17.014 atags += '^' * la
2025-07-02 06:41:17.014 btags += '^' * lb
2025-07-02 06:41:17.014 elif tag == 'delete':
2025-07-02 06:41:17.014 atags += '-' * la
2025-07-02 06:41:17.014 elif tag == 'insert':
2025-07-02 06:41:17.014 btags += '+' * lb
2025-07-02 06:41:17.014 elif tag == 'equal':
2025-07-02 06:41:17.014 atags += ' ' * la
2025-07-02 06:41:17.014 btags += ' ' * lb
2025-07-02 06:41:17.014 else:
2025-07-02 06:41:17.014 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.014 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.014 else:
2025-07-02 06:41:17.014 # the synch pair is identical
2025-07-02 06:41:17.015 yield ' ' + aelt
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015 # pump out diffs from after the synch point
2025-07-02 06:41:17.015 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.015 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.015 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.015 alo = 155, ahi = 1101
2025-07-02 06:41:17.015 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.015 blo = 155, bhi = 1101
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.015 g = []
2025-07-02 06:41:17.015 if alo < ahi:
2025-07-02 06:41:17.015 if blo < bhi:
2025-07-02 06:41:17.015 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.015 else:
2025-07-02 06:41:17.016 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.016 elif blo < bhi:
2025-07-02 06:41:17.016 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 > yield from g
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.016 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.016 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.016 alo = 155, ahi = 1101
2025-07-02 06:41:17.016 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.016 blo = 155, bhi = 1101
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.016 r"""
2025-07-02 06:41:17.016 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.016 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.016 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.017 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017 Example:
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017 >>> d = Differ()
2025-07-02 06:41:17.017 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.017 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.017 >>> print(''.join(results), end="")
2025-07-02 06:41:17.017 - abcDefghiJkl
2025-07-02 06:41:17.017 + abcdefGhijkl
2025-07-02 06:41:17.017 """
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.017 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.017 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.017 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.017 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017 # search for the pair that matches best without being identical
2025-07-02 06:41:17.018 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.018 # on junk -- unless we have to)
2025-07-02 06:41:17.018 for j in range(blo, bhi):
2025-07-02 06:41:17.018 bj = b[j]
2025-07-02 06:41:17.018 cruncher.set_seq2(bj)
2025-07-02 06:41:17.018 for i in range(alo, ahi):
2025-07-02 06:41:17.018 ai = a[i]
2025-07-02 06:41:17.018 if ai == bj:
2025-07-02 06:41:17.018 if eqi is None:
2025-07-02 06:41:17.018 eqi, eqj = i, j
2025-07-02 06:41:17.018 continue
2025-07-02 06:41:17.018 cruncher.set_seq1(ai)
2025-07-02 06:41:17.018 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.018 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.018 # compares by a factor of 3.
2025-07-02 06:41:17.018 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.018 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.018 # of the computation is cached by cruncher
2025-07-02 06:41:17.018 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.018 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.019 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.019 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.019 if best_ratio < cutoff:
2025-07-02 06:41:17.019 # no non-identical "pretty close" pair
2025-07-02 06:41:17.019 if eqi is None:
2025-07-02 06:41:17.019 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.019 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.019 return
2025-07-02 06:41:17.019 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.019 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.019 else:
2025-07-02 06:41:17.019 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.019 eqi = None
2025-07-02 06:41:17.019
2025-07-02 06:41:17.019 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.019 # identical
2025-07-02 06:41:17.019
2025-07-02 06:41:17.019 # pump out diffs from before the synch point
2025-07-02 06:41:17.019 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.019
2025-07-02 06:41:17.019 # do intraline marking on the synch pair
2025-07-02 06:41:17.020 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.020 if eqi is None:
2025-07-02 06:41:17.020 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.020 atags = btags = ""
2025-07-02 06:41:17.020 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.020 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.020 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.020 if tag == 'replace':
2025-07-02 06:41:17.020 atags += '^' * la
2025-07-02 06:41:17.020 btags += '^' * lb
2025-07-02 06:41:17.020 elif tag == 'delete':
2025-07-02 06:41:17.020 atags += '-' * la
2025-07-02 06:41:17.020 elif tag == 'insert':
2025-07-02 06:41:17.020 btags += '+' * lb
2025-07-02 06:41:17.020 elif tag == 'equal':
2025-07-02 06:41:17.020 atags += ' ' * la
2025-07-02 06:41:17.020 btags += ' ' * lb
2025-07-02 06:41:17.020 else:
2025-07-02 06:41:17.020 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.021 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.021 else:
2025-07-02 06:41:17.021 # the synch pair is identical
2025-07-02 06:41:17.021 yield ' ' + aelt
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021 # pump out diffs from after the synch point
2025-07-02 06:41:17.021 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.021 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.021 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.021 alo = 158, ahi = 1101
2025-07-02 06:41:17.021 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.021 blo = 158, bhi = 1101
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.021 g = []
2025-07-02 06:41:17.022 if alo < ahi:
2025-07-02 06:41:17.022 if blo < bhi:
2025-07-02 06:41:17.022 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.022 else:
2025-07-02 06:41:17.022 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.022 elif blo < bhi:
2025-07-02 06:41:17.022 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 > yield from g
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.022 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.022 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.022 alo = 158, ahi = 1101
2025-07-02 06:41:17.022 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.022 blo = 158, bhi = 1101
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.023 r"""
2025-07-02 06:41:17.023 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.023 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.023 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.023 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.023
2025-07-02 06:41:17.023 Example:
2025-07-02 06:41:17.023
2025-07-02 06:41:17.023 >>> d = Differ()
2025-07-02 06:41:17.023 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.023 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.023 >>> print(''.join(results), end="")
2025-07-02 06:41:17.023 - abcDefghiJkl
2025-07-02 06:41:17.023 + abcdefGhijkl
2025-07-02 06:41:17.023 """
2025-07-02 06:41:17.023
2025-07-02 06:41:17.023 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.023 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.024 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.024 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.024 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.024
2025-07-02 06:41:17.024 # search for the pair that matches best without being identical
2025-07-02 06:41:17.024 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.024 # on junk -- unless we have to)
2025-07-02 06:41:17.024 for j in range(blo, bhi):
2025-07-02 06:41:17.024 bj = b[j]
2025-07-02 06:41:17.024 cruncher.set_seq2(bj)
2025-07-02 06:41:17.024 for i in range(alo, ahi):
2025-07-02 06:41:17.024 ai = a[i]
2025-07-02 06:41:17.024 if ai == bj:
2025-07-02 06:41:17.024 if eqi is None:
2025-07-02 06:41:17.024 eqi, eqj = i, j
2025-07-02 06:41:17.024 continue
2025-07-02 06:41:17.024 cruncher.set_seq1(ai)
2025-07-02 06:41:17.024 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.024 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.025 # compares by a factor of 3.
2025-07-02 06:41:17.025 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.025 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.025 # of the computation is cached by cruncher
2025-07-02 06:41:17.025 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.025 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.025 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.025 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.025 if best_ratio < cutoff:
2025-07-02 06:41:17.025 # no non-identical "pretty close" pair
2025-07-02 06:41:17.025 if eqi is None:
2025-07-02 06:41:17.025 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.025 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.025 return
2025-07-02 06:41:17.025 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.025 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.025 else:
2025-07-02 06:41:17.025 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.025 eqi = None
2025-07-02 06:41:17.025
2025-07-02 06:41:17.026 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.026 # identical
2025-07-02 06:41:17.026
2025-07-02 06:41:17.026 # pump out diffs from before the synch point
2025-07-02 06:41:17.026 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.026
2025-07-02 06:41:17.026 # do intraline marking on the synch pair
2025-07-02 06:41:17.026 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.026 if eqi is None:
2025-07-02 06:41:17.026 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.026 atags = btags = ""
2025-07-02 06:41:17.026 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.026 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.026 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.026 if tag == 'replace':
2025-07-02 06:41:17.026 atags += '^' * la
2025-07-02 06:41:17.026 btags += '^' * lb
2025-07-02 06:41:17.026 elif tag == 'delete':
2025-07-02 06:41:17.026 atags += '-' * la
2025-07-02 06:41:17.026 elif tag == 'insert':
2025-07-02 06:41:17.026 btags += '+' * lb
2025-07-02 06:41:17.027 elif tag == 'equal':
2025-07-02 06:41:17.027 atags += ' ' * la
2025-07-02 06:41:17.027 btags += ' ' * lb
2025-07-02 06:41:17.027 else:
2025-07-02 06:41:17.027 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.027 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.027 else:
2025-07-02 06:41:17.027 # the synch pair is identical
2025-07-02 06:41:17.027 yield ' ' + aelt
2025-07-02 06:41:17.027
2025-07-02 06:41:17.027 # pump out diffs from after the synch point
2025-07-02 06:41:17.027 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.027
2025-07-02 06:41:17.027 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.027 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.027
2025-07-02 06:41:17.027 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.027 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.027 alo = 159, ahi = 1101
2025-07-02 06:41:17.027 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.028 blo = 159, bhi = 1101
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.028 g = []
2025-07-02 06:41:17.028 if alo < ahi:
2025-07-02 06:41:17.028 if blo < bhi:
2025-07-02 06:41:17.028 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.028 else:
2025-07-02 06:41:17.028 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.028 elif blo < bhi:
2025-07-02 06:41:17.028 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 > yield from g
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.028 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.028 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.028 alo = 159, ahi = 1101
2025-07-02 06:41:17.028 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.029 blo = 159, bhi = 1101
2025-07-02 06:41:17.029
2025-07-02 06:41:17.029 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.029 r"""
2025-07-02 06:41:17.029 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.029 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.029 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.029 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.029
2025-07-02 06:41:17.029 Example:
2025-07-02 06:41:17.029
2025-07-02 06:41:17.029 >>> d = Differ()
2025-07-02 06:41:17.029 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.029 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.029 >>> print(''.join(results), end="")
2025-07-02 06:41:17.030 - abcDefghiJkl
2025-07-02 06:41:17.030 + abcdefGhijkl
2025-07-02 06:41:17.030 """
2025-07-02 06:41:17.030
2025-07-02 06:41:17.030 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.030 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.030 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.030 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.030 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.030
2025-07-02 06:41:17.030 # search for the pair that matches best without being identical
2025-07-02 06:41:17.030 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.030 # on junk -- unless we have to)
2025-07-02 06:41:17.030 for j in range(blo, bhi):
2025-07-02 06:41:17.030 bj = b[j]
2025-07-02 06:41:17.030 cruncher.set_seq2(bj)
2025-07-02 06:41:17.030 for i in range(alo, ahi):
2025-07-02 06:41:17.031 ai = a[i]
2025-07-02 06:41:17.031 if ai == bj:
2025-07-02 06:41:17.031 if eqi is None:
2025-07-02 06:41:17.031 eqi, eqj = i, j
2025-07-02 06:41:17.031 continue
2025-07-02 06:41:17.031 cruncher.set_seq1(ai)
2025-07-02 06:41:17.031 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.031 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.031 # compares by a factor of 3.
2025-07-02 06:41:17.031 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.031 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.031 # of the computation is cached by cruncher
2025-07-02 06:41:17.031 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.031 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.031 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.031 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.031 if best_ratio < cutoff:
2025-07-02 06:41:17.031 # no non-identical "pretty close" pair
2025-07-02 06:41:17.031 if eqi is None:
2025-07-02 06:41:17.031 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.032 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.032 return
2025-07-02 06:41:17.032 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.032 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.032 else:
2025-07-02 06:41:17.032 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.032 eqi = None
2025-07-02 06:41:17.032
2025-07-02 06:41:17.032 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.032 # identical
2025-07-02 06:41:17.032
2025-07-02 06:41:17.032 # pump out diffs from before the synch point
2025-07-02 06:41:17.032 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.032
2025-07-02 06:41:17.032 # do intraline marking on the synch pair
2025-07-02 06:41:17.032 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.032 if eqi is None:
2025-07-02 06:41:17.032 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.032 atags = btags = ""
2025-07-02 06:41:17.032 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.033 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.033 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.033 if tag == 'replace':
2025-07-02 06:41:17.033 atags += '^' * la
2025-07-02 06:41:17.033 btags += '^' * lb
2025-07-02 06:41:17.033 elif tag == 'delete':
2025-07-02 06:41:17.033 atags += '-' * la
2025-07-02 06:41:17.033 elif tag == 'insert':
2025-07-02 06:41:17.033 btags += '+' * lb
2025-07-02 06:41:17.033 elif tag == 'equal':
2025-07-02 06:41:17.033 atags += ' ' * la
2025-07-02 06:41:17.033 btags += ' ' * lb
2025-07-02 06:41:17.033 else:
2025-07-02 06:41:17.033 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.033 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.033 else:
2025-07-02 06:41:17.033 # the synch pair is identical
2025-07-02 06:41:17.033 yield ' ' + aelt
2025-07-02 06:41:17.033
2025-07-02 06:41:17.033 # pump out diffs from after the synch point
2025-07-02 06:41:17.034 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.034
2025-07-02 06:41:17.034 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.034 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.034
2025-07-02 06:41:17.034 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.034 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.034 alo = 160, ahi = 1101
2025-07-02 06:41:17.034 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.034 blo = 160, bhi = 1101
2025-07-02 06:41:17.034
2025-07-02 06:41:17.034 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.034 g = []
2025-07-02 06:41:17.034 if alo < ahi:
2025-07-02 06:41:17.034 if blo < bhi:
2025-07-02 06:41:17.034 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.034 else:
2025-07-02 06:41:17.034 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.034 elif blo < bhi:
2025-07-02 06:41:17.034 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.034
2025-07-02 06:41:17.035 > yield from g
2025-07-02 06:41:17.035
2025-07-02 06:41:17.035 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.035 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.035
2025-07-02 06:41:17.035 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.035 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.035 alo = 160, ahi = 1101
2025-07-02 06:41:17.035 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.035 blo = 160, bhi = 1101
2025-07-02 06:41:17.035
2025-07-02 06:41:17.035 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.035 r"""
2025-07-02 06:41:17.035 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.035 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.035 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.035 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.035
2025-07-02 06:41:17.036 Example:
2025-07-02 06:41:17.036
2025-07-02 06:41:17.036 >>> d = Differ()
2025-07-02 06:41:17.036 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.036 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.036 >>> print(''.join(results), end="")
2025-07-02 06:41:17.036 - abcDefghiJkl
2025-07-02 06:41:17.036 + abcdefGhijkl
2025-07-02 06:41:17.036 """
2025-07-02 06:41:17.036
2025-07-02 06:41:17.036 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.036 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.036 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.036 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.036 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.036
2025-07-02 06:41:17.036 # search for the pair that matches best without being identical
2025-07-02 06:41:17.037 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.037 # on junk -- unless we have to)
2025-07-02 06:41:17.037 for j in range(blo, bhi):
2025-07-02 06:41:17.037 bj = b[j]
2025-07-02 06:41:17.037 cruncher.set_seq2(bj)
2025-07-02 06:41:17.037 for i in range(alo, ahi):
2025-07-02 06:41:17.037 ai = a[i]
2025-07-02 06:41:17.037 if ai == bj:
2025-07-02 06:41:17.037 if eqi is None:
2025-07-02 06:41:17.037 eqi, eqj = i, j
2025-07-02 06:41:17.037 continue
2025-07-02 06:41:17.037 cruncher.set_seq1(ai)
2025-07-02 06:41:17.037 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.037 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.037 # compares by a factor of 3.
2025-07-02 06:41:17.037 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.037 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.037 # of the computation is cached by cruncher
2025-07-02 06:41:17.037 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.037 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.037 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.038 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.038 if best_ratio < cutoff:
2025-07-02 06:41:17.038 # no non-identical "pretty close" pair
2025-07-02 06:41:17.038 if eqi is None:
2025-07-02 06:41:17.038 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.038 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.038 return
2025-07-02 06:41:17.038 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.038 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.038 else:
2025-07-02 06:41:17.038 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.038 eqi = None
2025-07-02 06:41:17.038
2025-07-02 06:41:17.038 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.038 # identical
2025-07-02 06:41:17.038
2025-07-02 06:41:17.038 # pump out diffs from before the synch point
2025-07-02 06:41:17.038 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.039
2025-07-02 06:41:17.039 # do intraline marking on the synch pair
2025-07-02 06:41:17.039 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.039 if eqi is None:
2025-07-02 06:41:17.039 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.039 atags = btags = ""
2025-07-02 06:41:17.039 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.039 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.039 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.039 if tag == 'replace':
2025-07-02 06:41:17.039 atags += '^' * la
2025-07-02 06:41:17.039 btags += '^' * lb
2025-07-02 06:41:17.039 elif tag == 'delete':
2025-07-02 06:41:17.039 atags += '-' * la
2025-07-02 06:41:17.039 elif tag == 'insert':
2025-07-02 06:41:17.039 btags += '+' * lb
2025-07-02 06:41:17.039 elif tag == 'equal':
2025-07-02 06:41:17.039 atags += ' ' * la
2025-07-02 06:41:17.039 btags += ' ' * lb
2025-07-02 06:41:17.040 else:
2025-07-02 06:41:17.040 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.040 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.040 else:
2025-07-02 06:41:17.040 # the synch pair is identical
2025-07-02 06:41:17.040 yield ' ' + aelt
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040 # pump out diffs from after the synch point
2025-07-02 06:41:17.040 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.040 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.040 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.040 alo = 161, ahi = 1101
2025-07-02 06:41:17.040 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.040 blo = 161, bhi = 1101
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.041 g = []
2025-07-02 06:41:17.041 if alo < ahi:
2025-07-02 06:41:17.041 if blo < bhi:
2025-07-02 06:41:17.041 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.041 else:
2025-07-02 06:41:17.041 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.041 elif blo < bhi:
2025-07-02 06:41:17.041 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.041
2025-07-02 06:41:17.041 > yield from g
2025-07-02 06:41:17.041
2025-07-02 06:41:17.041 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.041 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.041
2025-07-02 06:41:17.041 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.041 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.041 alo = 161, ahi = 1101
2025-07-02 06:41:17.041 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.041 blo = 161, bhi = 1101
2025-07-02 06:41:17.042
2025-07-02 06:41:17.042 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.042 r"""
2025-07-02 06:41:17.042 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.042 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.042 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.042 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.042
2025-07-02 06:41:17.042 Example:
2025-07-02 06:41:17.042
2025-07-02 06:41:17.042 >>> d = Differ()
2025-07-02 06:41:17.042 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.042 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.042 >>> print(''.join(results), end="")
2025-07-02 06:41:17.042 - abcDefghiJkl
2025-07-02 06:41:17.042 + abcdefGhijkl
2025-07-02 06:41:17.042 """
2025-07-02 06:41:17.042
2025-07-02 06:41:17.043 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.043 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.043 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.043 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.043 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.043
2025-07-02 06:41:17.043 # search for the pair that matches best without being identical
2025-07-02 06:41:17.043 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.043 # on junk -- unless we have to)
2025-07-02 06:41:17.043 for j in range(blo, bhi):
2025-07-02 06:41:17.043 bj = b[j]
2025-07-02 06:41:17.043 cruncher.set_seq2(bj)
2025-07-02 06:41:17.043 for i in range(alo, ahi):
2025-07-02 06:41:17.043 ai = a[i]
2025-07-02 06:41:17.043 if ai == bj:
2025-07-02 06:41:17.043 if eqi is None:
2025-07-02 06:41:17.043 eqi, eqj = i, j
2025-07-02 06:41:17.043 continue
2025-07-02 06:41:17.044 cruncher.set_seq1(ai)
2025-07-02 06:41:17.044 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.044 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.044 # compares by a factor of 3.
2025-07-02 06:41:17.044 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.044 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.044 # of the computation is cached by cruncher
2025-07-02 06:41:17.044 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.044 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.044 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.044 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.044 if best_ratio < cutoff:
2025-07-02 06:41:17.044 # no non-identical "pretty close" pair
2025-07-02 06:41:17.044 if eqi is None:
2025-07-02 06:41:17.044 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.044 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.044 return
2025-07-02 06:41:17.044 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.044 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.044 else:
2025-07-02 06:41:17.045 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.045 eqi = None
2025-07-02 06:41:17.045
2025-07-02 06:41:17.045 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.045 # identical
2025-07-02 06:41:17.045
2025-07-02 06:41:17.045 # pump out diffs from before the synch point
2025-07-02 06:41:17.045 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.045
2025-07-02 06:41:17.045 # do intraline marking on the synch pair
2025-07-02 06:41:17.045 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.045 if eqi is None:
2025-07-02 06:41:17.045 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.045 atags = btags = ""
2025-07-02 06:41:17.045 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.045 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.045 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.045 if tag == 'replace':
2025-07-02 06:41:17.046 atags += '^' * la
2025-07-02 06:41:17.046 btags += '^' * lb
2025-07-02 06:41:17.046 elif tag == 'delete':
2025-07-02 06:41:17.046 atags += '-' * la
2025-07-02 06:41:17.046 elif tag == 'insert':
2025-07-02 06:41:17.046 btags += '+' * lb
2025-07-02 06:41:17.046 elif tag == 'equal':
2025-07-02 06:41:17.046 atags += ' ' * la
2025-07-02 06:41:17.046 btags += ' ' * lb
2025-07-02 06:41:17.046 else:
2025-07-02 06:41:17.046 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.046 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.046 else:
2025-07-02 06:41:17.046 # the synch pair is identical
2025-07-02 06:41:17.046 yield ' ' + aelt
2025-07-02 06:41:17.046
2025-07-02 06:41:17.046 # pump out diffs from after the synch point
2025-07-02 06:41:17.046 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.046
2025-07-02 06:41:17.046 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.047 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.047
2025-07-02 06:41:17.047 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.047 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.047 alo = 162, ahi = 1101
2025-07-02 06:41:17.047 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.047 blo = 162, bhi = 1101
2025-07-02 06:41:17.047
2025-07-02 06:41:17.047 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.047 g = []
2025-07-02 06:41:17.047 if alo < ahi:
2025-07-02 06:41:17.047 if blo < bhi:
2025-07-02 06:41:17.047 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.047 else:
2025-07-02 06:41:17.047 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.047 elif blo < bhi:
2025-07-02 06:41:17.047 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.047
2025-07-02 06:41:17.048 > yield from g
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.048 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.048 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.048 alo = 162, ahi = 1101
2025-07-02 06:41:17.048 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.048 blo = 162, bhi = 1101
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.048 r"""
2025-07-02 06:41:17.048 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.048 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.048 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.048 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048 Example:
2025-07-02 06:41:17.049
2025-07-02 06:41:17.049 >>> d = Differ()
2025-07-02 06:41:17.049 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.049 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.049 >>> print(''.join(results), end="")
2025-07-02 06:41:17.049 - abcDefghiJkl
2025-07-02 06:41:17.049 + abcdefGhijkl
2025-07-02 06:41:17.049 """
2025-07-02 06:41:17.049
2025-07-02 06:41:17.049 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.049 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.049 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.049 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.049 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.049
2025-07-02 06:41:17.049 # search for the pair that matches best without being identical
2025-07-02 06:41:17.049 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.049 # on junk -- unless we have to)
2025-07-02 06:41:17.050 for j in range(blo, bhi):
2025-07-02 06:41:17.050 bj = b[j]
2025-07-02 06:41:17.050 cruncher.set_seq2(bj)
2025-07-02 06:41:17.050 for i in range(alo, ahi):
2025-07-02 06:41:17.050 ai = a[i]
2025-07-02 06:41:17.050 if ai == bj:
2025-07-02 06:41:17.050 if eqi is None:
2025-07-02 06:41:17.050 eqi, eqj = i, j
2025-07-02 06:41:17.050 continue
2025-07-02 06:41:17.050 cruncher.set_seq1(ai)
2025-07-02 06:41:17.050 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.050 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.050 # compares by a factor of 3.
2025-07-02 06:41:17.050 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.050 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.050 # of the computation is cached by cruncher
2025-07-02 06:41:17.050 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.050 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.050 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.050 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.050 if best_ratio < cutoff:
2025-07-02 06:41:17.051 # no non-identical "pretty close" pair
2025-07-02 06:41:17.051 if eqi is None:
2025-07-02 06:41:17.051 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.051 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.051 return
2025-07-02 06:41:17.051 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.051 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.051 else:
2025-07-02 06:41:17.051 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.051 eqi = None
2025-07-02 06:41:17.051
2025-07-02 06:41:17.051 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.051 # identical
2025-07-02 06:41:17.051
2025-07-02 06:41:17.051 # pump out diffs from before the synch point
2025-07-02 06:41:17.051 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.051
2025-07-02 06:41:17.051 # do intraline marking on the synch pair
2025-07-02 06:41:17.051 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.051 if eqi is None:
2025-07-02 06:41:17.052 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.052 atags = btags = ""
2025-07-02 06:41:17.052 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.052 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.052 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.052 if tag == 'replace':
2025-07-02 06:41:17.052 atags += '^' * la
2025-07-02 06:41:17.052 btags += '^' * lb
2025-07-02 06:41:17.052 elif tag == 'delete':
2025-07-02 06:41:17.052 atags += '-' * la
2025-07-02 06:41:17.052 elif tag == 'insert':
2025-07-02 06:41:17.052 btags += '+' * lb
2025-07-02 06:41:17.052 elif tag == 'equal':
2025-07-02 06:41:17.052 atags += ' ' * la
2025-07-02 06:41:17.052 btags += ' ' * lb
2025-07-02 06:41:17.052 else:
2025-07-02 06:41:17.052 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.052 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.052 else:
2025-07-02 06:41:17.052 # the synch pair is identical
2025-07-02 06:41:17.052 yield ' ' + aelt
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053 # pump out diffs from after the synch point
2025-07-02 06:41:17.053 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.053 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.053 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.053 alo = 163, ahi = 1101
2025-07-02 06:41:17.053 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.053 blo = 163, bhi = 1101
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.053 g = []
2025-07-02 06:41:17.053 if alo < ahi:
2025-07-02 06:41:17.053 if blo < bhi:
2025-07-02 06:41:17.053 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.053 else:
2025-07-02 06:41:17.053 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.054 elif blo < bhi:
2025-07-02 06:41:17.054 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 > yield from g
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.054 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.054 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.054 alo = 163, ahi = 1101
2025-07-02 06:41:17.054 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.054 blo = 163, bhi = 1101
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.054 r"""
2025-07-02 06:41:17.054 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.054 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.054 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.054 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055 Example:
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055 >>> d = Differ()
2025-07-02 06:41:17.055 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.055 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.055 >>> print(''.join(results), end="")
2025-07-02 06:41:17.055 - abcDefghiJkl
2025-07-02 06:41:17.055 + abcdefGhijkl
2025-07-02 06:41:17.055 """
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.055 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.055 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.055 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.055 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055 # search for the pair that matches best without being identical
2025-07-02 06:41:17.056 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.056 # on junk -- unless we have to)
2025-07-02 06:41:17.056 for j in range(blo, bhi):
2025-07-02 06:41:17.056 bj = b[j]
2025-07-02 06:41:17.056 cruncher.set_seq2(bj)
2025-07-02 06:41:17.056 for i in range(alo, ahi):
2025-07-02 06:41:17.056 ai = a[i]
2025-07-02 06:41:17.056 if ai == bj:
2025-07-02 06:41:17.056 if eqi is None:
2025-07-02 06:41:17.056 eqi, eqj = i, j
2025-07-02 06:41:17.056 continue
2025-07-02 06:41:17.056 cruncher.set_seq1(ai)
2025-07-02 06:41:17.056 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.056 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.056 # compares by a factor of 3.
2025-07-02 06:41:17.056 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.056 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.056 # of the computation is cached by cruncher
2025-07-02 06:41:17.056 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.057 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.057 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.057 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.057 if best_ratio < cutoff:
2025-07-02 06:41:17.057 # no non-identical "pretty close" pair
2025-07-02 06:41:17.057 if eqi is None:
2025-07-02 06:41:17.057 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.057 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.057 return
2025-07-02 06:41:17.057 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.057 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.057 else:
2025-07-02 06:41:17.057 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.057 eqi = None
2025-07-02 06:41:17.057
2025-07-02 06:41:17.057 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.057 # identical
2025-07-02 06:41:17.057
2025-07-02 06:41:17.057 # pump out diffs from before the synch point
2025-07-02 06:41:17.057 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.058
2025-07-02 06:41:17.058 # do intraline marking on the synch pair
2025-07-02 06:41:17.058 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.058 if eqi is None:
2025-07-02 06:41:17.058 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.058 atags = btags = ""
2025-07-02 06:41:17.058 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.058 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.058 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.058 if tag == 'replace':
2025-07-02 06:41:17.058 atags += '^' * la
2025-07-02 06:41:17.058 btags += '^' * lb
2025-07-02 06:41:17.058 elif tag == 'delete':
2025-07-02 06:41:17.058 atags += '-' * la
2025-07-02 06:41:17.058 elif tag == 'insert':
2025-07-02 06:41:17.058 btags += '+' * lb
2025-07-02 06:41:17.058 elif tag == 'equal':
2025-07-02 06:41:17.058 atags += ' ' * la
2025-07-02 06:41:17.058 btags += ' ' * lb
2025-07-02 06:41:17.058 else:
2025-07-02 06:41:17.059 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.059 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.059 else:
2025-07-02 06:41:17.059 # the synch pair is identical
2025-07-02 06:41:17.059 yield ' ' + aelt
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059 # pump out diffs from after the synch point
2025-07-02 06:41:17.059 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.059 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.059 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.059 alo = 164, ahi = 1101
2025-07-02 06:41:17.059 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.059 blo = 164, bhi = 1101
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.059 g = []
2025-07-02 06:41:17.060 if alo < ahi:
2025-07-02 06:41:17.060 if blo < bhi:
2025-07-02 06:41:17.060 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.060 else:
2025-07-02 06:41:17.060 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.060 elif blo < bhi:
2025-07-02 06:41:17.060 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 > yield from g
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.060 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.060 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.060 alo = 164, ahi = 1101
2025-07-02 06:41:17.060 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.060 blo = 164, bhi = 1101
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.060 r"""
2025-07-02 06:41:17.061 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.061 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.061 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.061 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.061
2025-07-02 06:41:17.061 Example:
2025-07-02 06:41:17.061
2025-07-02 06:41:17.061 >>> d = Differ()
2025-07-02 06:41:17.061 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.061 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.061 >>> print(''.join(results), end="")
2025-07-02 06:41:17.061 - abcDefghiJkl
2025-07-02 06:41:17.061 + abcdefGhijkl
2025-07-02 06:41:17.061 """
2025-07-02 06:41:17.062
2025-07-02 06:41:17.062 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.062 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.062 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.062 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.062 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.062
2025-07-02 06:41:17.062 # search for the pair that matches best without being identical
2025-07-02 06:41:17.062 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.062 # on junk -- unless we have to)
2025-07-02 06:41:17.062 for j in range(blo, bhi):
2025-07-02 06:41:17.062 bj = b[j]
2025-07-02 06:41:17.062 cruncher.set_seq2(bj)
2025-07-02 06:41:17.062 for i in range(alo, ahi):
2025-07-02 06:41:17.062 ai = a[i]
2025-07-02 06:41:17.062 if ai == bj:
2025-07-02 06:41:17.062 if eqi is None:
2025-07-02 06:41:17.062 eqi, eqj = i, j
2025-07-02 06:41:17.062 continue
2025-07-02 06:41:17.062 cruncher.set_seq1(ai)
2025-07-02 06:41:17.063 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.063 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.063 # compares by a factor of 3.
2025-07-02 06:41:17.063 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.063 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.063 # of the computation is cached by cruncher
2025-07-02 06:41:17.063 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.063 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.063 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.063 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.063 if best_ratio < cutoff:
2025-07-02 06:41:17.063 # no non-identical "pretty close" pair
2025-07-02 06:41:17.063 if eqi is None:
2025-07-02 06:41:17.063 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.063 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.063 return
2025-07-02 06:41:17.063 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.063 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.063 else:
2025-07-02 06:41:17.064 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.064 eqi = None
2025-07-02 06:41:17.064
2025-07-02 06:41:17.064 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.064 # identical
2025-07-02 06:41:17.064
2025-07-02 06:41:17.064 # pump out diffs from before the synch point
2025-07-02 06:41:17.064 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.064
2025-07-02 06:41:17.064 # do intraline marking on the synch pair
2025-07-02 06:41:17.064 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.064 if eqi is None:
2025-07-02 06:41:17.064 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.064 atags = btags = ""
2025-07-02 06:41:17.064 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.064 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.064 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.064 if tag == 'replace':
2025-07-02 06:41:17.064 atags += '^' * la
2025-07-02 06:41:17.065 btags += '^' * lb
2025-07-02 06:41:17.065 elif tag == 'delete':
2025-07-02 06:41:17.065 atags += '-' * la
2025-07-02 06:41:17.065 elif tag == 'insert':
2025-07-02 06:41:17.065 btags += '+' * lb
2025-07-02 06:41:17.065 elif tag == 'equal':
2025-07-02 06:41:17.065 atags += ' ' * la
2025-07-02 06:41:17.065 btags += ' ' * lb
2025-07-02 06:41:17.065 else:
2025-07-02 06:41:17.065 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.065 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.065 else:
2025-07-02 06:41:17.065 # the synch pair is identical
2025-07-02 06:41:17.065 yield ' ' + aelt
2025-07-02 06:41:17.065
2025-07-02 06:41:17.065 # pump out diffs from after the synch point
2025-07-02 06:41:17.065 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.065
2025-07-02 06:41:17.065 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.066 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.066
2025-07-02 06:41:17.066 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.066 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.066 alo = 165, ahi = 1101
2025-07-02 06:41:17.066 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.066 blo = 165, bhi = 1101
2025-07-02 06:41:17.066
2025-07-02 06:41:17.066 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.066 g = []
2025-07-02 06:41:17.066 if alo < ahi:
2025-07-02 06:41:17.066 if blo < bhi:
2025-07-02 06:41:17.066 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.066 else:
2025-07-02 06:41:17.066 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.066 elif blo < bhi:
2025-07-02 06:41:17.066 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.066
2025-07-02 06:41:17.066 > yield from g
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.067 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.067 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.067 alo = 165, ahi = 1101
2025-07-02 06:41:17.067 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.067 blo = 165, bhi = 1101
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.067 r"""
2025-07-02 06:41:17.067 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.067 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.067 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.067 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067 Example:
2025-07-02 06:41:17.067
2025-07-02 06:41:17.068 >>> d = Differ()
2025-07-02 06:41:17.068 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.068 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.068 >>> print(''.join(results), end="")
2025-07-02 06:41:17.068 - abcDefghiJkl
2025-07-02 06:41:17.068 + abcdefGhijkl
2025-07-02 06:41:17.068 """
2025-07-02 06:41:17.068
2025-07-02 06:41:17.068 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.068 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.068 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.068 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.068 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.068
2025-07-02 06:41:17.068 # search for the pair that matches best without being identical
2025-07-02 06:41:17.068 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.068 # on junk -- unless we have to)
2025-07-02 06:41:17.069 for j in range(blo, bhi):
2025-07-02 06:41:17.069 bj = b[j]
2025-07-02 06:41:17.069 cruncher.set_seq2(bj)
2025-07-02 06:41:17.069 for i in range(alo, ahi):
2025-07-02 06:41:17.069 ai = a[i]
2025-07-02 06:41:17.069 if ai == bj:
2025-07-02 06:41:17.069 if eqi is None:
2025-07-02 06:41:17.069 eqi, eqj = i, j
2025-07-02 06:41:17.069 continue
2025-07-02 06:41:17.069 cruncher.set_seq1(ai)
2025-07-02 06:41:17.069 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.069 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.069 # compares by a factor of 3.
2025-07-02 06:41:17.069 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.069 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.069 # of the computation is cached by cruncher
2025-07-02 06:41:17.069 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.069 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.069 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.070 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.070 if best_ratio < cutoff:
2025-07-02 06:41:17.070 # no non-identical "pretty close" pair
2025-07-02 06:41:17.070 if eqi is None:
2025-07-02 06:41:17.070 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.070 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.070 return
2025-07-02 06:41:17.070 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.070 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.070 else:
2025-07-02 06:41:17.070 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.070 eqi = None
2025-07-02 06:41:17.070
2025-07-02 06:41:17.070 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.070 # identical
2025-07-02 06:41:17.070
2025-07-02 06:41:17.070 # pump out diffs from before the synch point
2025-07-02 06:41:17.070 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.070
2025-07-02 06:41:17.070 # do intraline marking on the synch pair
2025-07-02 06:41:17.071 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.071 if eqi is None:
2025-07-02 06:41:17.071 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.071 atags = btags = ""
2025-07-02 06:41:17.071 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.071 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.071 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.071 if tag == 'replace':
2025-07-02 06:41:17.071 atags += '^' * la
2025-07-02 06:41:17.071 btags += '^' * lb
2025-07-02 06:41:17.071 elif tag == 'delete':
2025-07-02 06:41:17.071 atags += '-' * la
2025-07-02 06:41:17.071 elif tag == 'insert':
2025-07-02 06:41:17.071 btags += '+' * lb
2025-07-02 06:41:17.071 elif tag == 'equal':
2025-07-02 06:41:17.071 atags += ' ' * la
2025-07-02 06:41:17.071 btags += ' ' * lb
2025-07-02 06:41:17.071 else:
2025-07-02 06:41:17.071 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.071 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.072 else:
2025-07-02 06:41:17.072 # the synch pair is identical
2025-07-02 06:41:17.072 yield ' ' + aelt
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072 # pump out diffs from after the synch point
2025-07-02 06:41:17.072 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.072 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.072 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.072 alo = 166, ahi = 1101
2025-07-02 06:41:17.072 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.072 blo = 166, bhi = 1101
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.072 g = []
2025-07-02 06:41:17.072 if alo < ahi:
2025-07-02 06:41:17.072 if blo < bhi:
2025-07-02 06:41:17.073 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.073 else:
2025-07-02 06:41:17.073 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.073 elif blo < bhi:
2025-07-02 06:41:17.073 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 > yield from g
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.073 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.073 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.073 alo = 166, ahi = 1101
2025-07-02 06:41:17.073 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.073 blo = 166, bhi = 1101
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.074 r"""
2025-07-02 06:41:17.074 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.074 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.074 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.074 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.074
2025-07-02 06:41:17.074 Example:
2025-07-02 06:41:17.074
2025-07-02 06:41:17.074 >>> d = Differ()
2025-07-02 06:41:17.074 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.074 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.074 >>> print(''.join(results), end="")
2025-07-02 06:41:17.074 - abcDefghiJkl
2025-07-02 06:41:17.074 + abcdefGhijkl
2025-07-02 06:41:17.074 """
2025-07-02 06:41:17.074
2025-07-02 06:41:17.074 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.074 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.075 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.075 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.075 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.075
2025-07-02 06:41:17.075 # search for the pair that matches best without being identical
2025-07-02 06:41:17.075 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.075 # on junk -- unless we have to)
2025-07-02 06:41:17.075 for j in range(blo, bhi):
2025-07-02 06:41:17.075 bj = b[j]
2025-07-02 06:41:17.075 cruncher.set_seq2(bj)
2025-07-02 06:41:17.075 for i in range(alo, ahi):
2025-07-02 06:41:17.075 ai = a[i]
2025-07-02 06:41:17.075 if ai == bj:
2025-07-02 06:41:17.075 if eqi is None:
2025-07-02 06:41:17.075 eqi, eqj = i, j
2025-07-02 06:41:17.075 continue
2025-07-02 06:41:17.075 cruncher.set_seq1(ai)
2025-07-02 06:41:17.075 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.075 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.076 # compares by a factor of 3.
2025-07-02 06:41:17.076 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.076 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.076 # of the computation is cached by cruncher
2025-07-02 06:41:17.076 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.076 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.076 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.076 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.076 if best_ratio < cutoff:
2025-07-02 06:41:17.076 # no non-identical "pretty close" pair
2025-07-02 06:41:17.076 if eqi is None:
2025-07-02 06:41:17.076 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.076 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.076 return
2025-07-02 06:41:17.076 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.076 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.076 else:
2025-07-02 06:41:17.076 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.076 eqi = None
2025-07-02 06:41:17.076
2025-07-02 06:41:17.076 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.077 # identical
2025-07-02 06:41:17.077
2025-07-02 06:41:17.077 # pump out diffs from before the synch point
2025-07-02 06:41:17.077 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.077
2025-07-02 06:41:17.077 # do intraline marking on the synch pair
2025-07-02 06:41:17.077 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.077 if eqi is None:
2025-07-02 06:41:17.077 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.077 atags = btags = ""
2025-07-02 06:41:17.077 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.077 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.077 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.077 if tag == 'replace':
2025-07-02 06:41:17.077 atags += '^' * la
2025-07-02 06:41:17.077 btags += '^' * lb
2025-07-02 06:41:17.077 elif tag == 'delete':
2025-07-02 06:41:17.077 atags += '-' * la
2025-07-02 06:41:17.078 elif tag == 'insert':
2025-07-02 06:41:17.078 btags += '+' * lb
2025-07-02 06:41:17.078 elif tag == 'equal':
2025-07-02 06:41:17.078 atags += ' ' * la
2025-07-02 06:41:17.078 btags += ' ' * lb
2025-07-02 06:41:17.078 else:
2025-07-02 06:41:17.078 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.078 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.078 else:
2025-07-02 06:41:17.078 # the synch pair is identical
2025-07-02 06:41:17.078 yield ' ' + aelt
2025-07-02 06:41:17.078
2025-07-02 06:41:17.078 # pump out diffs from after the synch point
2025-07-02 06:41:17.078 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.078
2025-07-02 06:41:17.078 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.078 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.078
2025-07-02 06:41:17.078 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.078 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.078 alo = 167, ahi = 1101
2025-07-02 06:41:17.079 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.079 blo = 167, bhi = 1101
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.079 g = []
2025-07-02 06:41:17.079 if alo < ahi:
2025-07-02 06:41:17.079 if blo < bhi:
2025-07-02 06:41:17.079 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.079 else:
2025-07-02 06:41:17.079 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.079 elif blo < bhi:
2025-07-02 06:41:17.079 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 > yield from g
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.079 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.079 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.080 alo = 167, ahi = 1101
2025-07-02 06:41:17.080 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.080 blo = 167, bhi = 1101
2025-07-02 06:41:17.080
2025-07-02 06:41:17.080 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.080 r"""
2025-07-02 06:41:17.080 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.080 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.080 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.080 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.080
2025-07-02 06:41:17.080 Example:
2025-07-02 06:41:17.080
2025-07-02 06:41:17.080 >>> d = Differ()
2025-07-02 06:41:17.080 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.080 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.080 >>> print(''.join(results), end="")
2025-07-02 06:41:17.080 - abcDefghiJkl
2025-07-02 06:41:17.080 + abcdefGhijkl
2025-07-02 06:41:17.081 """
2025-07-02 06:41:17.081
2025-07-02 06:41:17.081 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.081 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.081 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.081 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.081 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.081
2025-07-02 06:41:17.081 # search for the pair that matches best without being identical
2025-07-02 06:41:17.081 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.081 # on junk -- unless we have to)
2025-07-02 06:41:17.081 for j in range(blo, bhi):
2025-07-02 06:41:17.081 bj = b[j]
2025-07-02 06:41:17.081 cruncher.set_seq2(bj)
2025-07-02 06:41:17.081 for i in range(alo, ahi):
2025-07-02 06:41:17.081 ai = a[i]
2025-07-02 06:41:17.081 if ai == bj:
2025-07-02 06:41:17.081 if eqi is None:
2025-07-02 06:41:17.081 eqi, eqj = i, j
2025-07-02 06:41:17.081 continue
2025-07-02 06:41:17.082 cruncher.set_seq1(ai)
2025-07-02 06:41:17.082 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.082 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.082 # compares by a factor of 3.
2025-07-02 06:41:17.082 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.082 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.082 # of the computation is cached by cruncher
2025-07-02 06:41:17.082 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.082 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.082 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.082 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.082 if best_ratio < cutoff:
2025-07-02 06:41:17.082 # no non-identical "pretty close" pair
2025-07-02 06:41:17.082 if eqi is None:
2025-07-02 06:41:17.082 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.082 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.082 return
2025-07-02 06:41:17.082 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.082 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.083 else:
2025-07-02 06:41:17.083 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.083 eqi = None
2025-07-02 06:41:17.083
2025-07-02 06:41:17.083 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.083 # identical
2025-07-02 06:41:17.083
2025-07-02 06:41:17.083 # pump out diffs from before the synch point
2025-07-02 06:41:17.083 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.083
2025-07-02 06:41:17.083 # do intraline marking on the synch pair
2025-07-02 06:41:17.083 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.083 if eqi is None:
2025-07-02 06:41:17.083 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.083 atags = btags = ""
2025-07-02 06:41:17.083 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.083 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.083 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.083 if tag == 'replace':
2025-07-02 06:41:17.083 atags += '^' * la
2025-07-02 06:41:17.084 btags += '^' * lb
2025-07-02 06:41:17.084 elif tag == 'delete':
2025-07-02 06:41:17.084 atags += '-' * la
2025-07-02 06:41:17.084 elif tag == 'insert':
2025-07-02 06:41:17.084 btags += '+' * lb
2025-07-02 06:41:17.084 elif tag == 'equal':
2025-07-02 06:41:17.084 atags += ' ' * la
2025-07-02 06:41:17.084 btags += ' ' * lb
2025-07-02 06:41:17.084 else:
2025-07-02 06:41:17.084 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.084 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.084 else:
2025-07-02 06:41:17.084 # the synch pair is identical
2025-07-02 06:41:17.084 yield ' ' + aelt
2025-07-02 06:41:17.084
2025-07-02 06:41:17.084 # pump out diffs from after the synch point
2025-07-02 06:41:17.084 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.084
2025-07-02 06:41:17.084 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.084 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.085 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.085 alo = 168, ahi = 1101
2025-07-02 06:41:17.085 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.085 blo = 168, bhi = 1101
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.085 g = []
2025-07-02 06:41:17.085 if alo < ahi:
2025-07-02 06:41:17.085 if blo < bhi:
2025-07-02 06:41:17.085 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.085 else:
2025-07-02 06:41:17.085 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.085 elif blo < bhi:
2025-07-02 06:41:17.085 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 > yield from g
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.086 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.086 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.086 alo = 168, ahi = 1101
2025-07-02 06:41:17.086 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.086 blo = 168, bhi = 1101
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.086 r"""
2025-07-02 06:41:17.086 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.086 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.086 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.086 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086 Example:
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086 >>> d = Differ()
2025-07-02 06:41:17.086 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.086 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.086 >>> print(''.join(results), end="")
2025-07-02 06:41:17.087 - abcDefghiJkl
2025-07-02 06:41:17.087 + abcdefGhijkl
2025-07-02 06:41:17.087 """
2025-07-02 06:41:17.087
2025-07-02 06:41:17.087 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.087 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.087 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.087 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.087 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.087
2025-07-02 06:41:17.087 # search for the pair that matches best without being identical
2025-07-02 06:41:17.087 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.087 # on junk -- unless we have to)
2025-07-02 06:41:17.087 for j in range(blo, bhi):
2025-07-02 06:41:17.087 bj = b[j]
2025-07-02 06:41:17.087 cruncher.set_seq2(bj)
2025-07-02 06:41:17.087 for i in range(alo, ahi):
2025-07-02 06:41:17.087 ai = a[i]
2025-07-02 06:41:17.088 if ai == bj:
2025-07-02 06:41:17.088 if eqi is None:
2025-07-02 06:41:17.088 eqi, eqj = i, j
2025-07-02 06:41:17.088 continue
2025-07-02 06:41:17.088 cruncher.set_seq1(ai)
2025-07-02 06:41:17.088 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.088 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.088 # compares by a factor of 3.
2025-07-02 06:41:17.088 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.088 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.088 # of the computation is cached by cruncher
2025-07-02 06:41:17.088 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.088 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.088 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.088 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.088 if best_ratio < cutoff:
2025-07-02 06:41:17.088 # no non-identical "pretty close" pair
2025-07-02 06:41:17.088 if eqi is None:
2025-07-02 06:41:17.088 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.089 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.089 return
2025-07-02 06:41:17.089 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.089 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.089 else:
2025-07-02 06:41:17.089 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.089 eqi = None
2025-07-02 06:41:17.089
2025-07-02 06:41:17.089 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.089 # identical
2025-07-02 06:41:17.089
2025-07-02 06:41:17.089 # pump out diffs from before the synch point
2025-07-02 06:41:17.089 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.089
2025-07-02 06:41:17.089 # do intraline marking on the synch pair
2025-07-02 06:41:17.089 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.089 if eqi is None:
2025-07-02 06:41:17.089 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.089 atags = btags = ""
2025-07-02 06:41:17.089 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.089 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.090 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.090 if tag == 'replace':
2025-07-02 06:41:17.090 atags += '^' * la
2025-07-02 06:41:17.090 btags += '^' * lb
2025-07-02 06:41:17.090 elif tag == 'delete':
2025-07-02 06:41:17.090 atags += '-' * la
2025-07-02 06:41:17.090 elif tag == 'insert':
2025-07-02 06:41:17.090 btags += '+' * lb
2025-07-02 06:41:17.090 elif tag == 'equal':
2025-07-02 06:41:17.090 atags += ' ' * la
2025-07-02 06:41:17.090 btags += ' ' * lb
2025-07-02 06:41:17.090 else:
2025-07-02 06:41:17.090 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.090 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.090 else:
2025-07-02 06:41:17.090 # the synch pair is identical
2025-07-02 06:41:17.090 yield ' ' + aelt
2025-07-02 06:41:17.090
2025-07-02 06:41:17.090 # pump out diffs from after the synch point
2025-07-02 06:41:17.090 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.091
2025-07-02 06:41:17.091 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.091 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.091
2025-07-02 06:41:17.091 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.091 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.091 alo = 169, ahi = 1101
2025-07-02 06:41:17.091 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.091 blo = 169, bhi = 1101
2025-07-02 06:41:17.091
2025-07-02 06:41:17.091 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.091 g = []
2025-07-02 06:41:17.091 if alo < ahi:
2025-07-02 06:41:17.091 if blo < bhi:
2025-07-02 06:41:17.091 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.091 else:
2025-07-02 06:41:17.091 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.091 elif blo < bhi:
2025-07-02 06:41:17.091 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 > yield from g
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.092 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.092 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.092 alo = 169, ahi = 1101
2025-07-02 06:41:17.092 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.092 blo = 169, bhi = 1101
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.092 r"""
2025-07-02 06:41:17.092 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.092 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.092 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.092 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 Example:
2025-07-02 06:41:17.093
2025-07-02 06:41:17.093 >>> d = Differ()
2025-07-02 06:41:17.093 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.093 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.093 >>> print(''.join(results), end="")
2025-07-02 06:41:17.093 - abcDefghiJkl
2025-07-02 06:41:17.093 + abcdefGhijkl
2025-07-02 06:41:17.093 """
2025-07-02 06:41:17.093
2025-07-02 06:41:17.093 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.093 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.093 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.093 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.093 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.093
2025-07-02 06:41:17.093 # search for the pair that matches best without being identical
2025-07-02 06:41:17.094 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.094 # on junk -- unless we have to)
2025-07-02 06:41:17.094 for j in range(blo, bhi):
2025-07-02 06:41:17.094 bj = b[j]
2025-07-02 06:41:17.094 cruncher.set_seq2(bj)
2025-07-02 06:41:17.094 for i in range(alo, ahi):
2025-07-02 06:41:17.094 ai = a[i]
2025-07-02 06:41:17.094 if ai == bj:
2025-07-02 06:41:17.094 if eqi is None:
2025-07-02 06:41:17.094 eqi, eqj = i, j
2025-07-02 06:41:17.094 continue
2025-07-02 06:41:17.094 cruncher.set_seq1(ai)
2025-07-02 06:41:17.094 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.094 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.094 # compares by a factor of 3.
2025-07-02 06:41:17.094 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.094 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.094 # of the computation is cached by cruncher
2025-07-02 06:41:17.094 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.094 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.095 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.095 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.095 if best_ratio < cutoff:
2025-07-02 06:41:17.095 # no non-identical "pretty close" pair
2025-07-02 06:41:17.095 if eqi is None:
2025-07-02 06:41:17.095 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.095 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.095 return
2025-07-02 06:41:17.095 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.095 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.095 else:
2025-07-02 06:41:17.095 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.095 eqi = None
2025-07-02 06:41:17.095
2025-07-02 06:41:17.095 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.095 # identical
2025-07-02 06:41:17.095
2025-07-02 06:41:17.095 # pump out diffs from before the synch point
2025-07-02 06:41:17.095 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.095
2025-07-02 06:41:17.096 # do intraline marking on the synch pair
2025-07-02 06:41:17.096 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.096 if eqi is None:
2025-07-02 06:41:17.096 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.096 atags = btags = ""
2025-07-02 06:41:17.096 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.096 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.096 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.096 if tag == 'replace':
2025-07-02 06:41:17.096 atags += '^' * la
2025-07-02 06:41:17.096 btags += '^' * lb
2025-07-02 06:41:17.096 elif tag == 'delete':
2025-07-02 06:41:17.096 atags += '-' * la
2025-07-02 06:41:17.096 elif tag == 'insert':
2025-07-02 06:41:17.096 btags += '+' * lb
2025-07-02 06:41:17.096 elif tag == 'equal':
2025-07-02 06:41:17.096 atags += ' ' * la
2025-07-02 06:41:17.096 btags += ' ' * lb
2025-07-02 06:41:17.096 else:
2025-07-02 06:41:17.096 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.096 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.097 else:
2025-07-02 06:41:17.097 # the synch pair is identical
2025-07-02 06:41:17.097 yield ' ' + aelt
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097 # pump out diffs from after the synch point
2025-07-02 06:41:17.097 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.097 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.097 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.097 alo = 170, ahi = 1101
2025-07-02 06:41:17.097 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.097 blo = 170, bhi = 1101
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.097 g = []
2025-07-02 06:41:17.097 if alo < ahi:
2025-07-02 06:41:17.097 if blo < bhi:
2025-07-02 06:41:17.098 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.098 else:
2025-07-02 06:41:17.098 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.098 elif blo < bhi:
2025-07-02 06:41:17.098 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 > yield from g
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.098 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.098 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.098 alo = 170, ahi = 1101
2025-07-02 06:41:17.098 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.098 blo = 170, bhi = 1101
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.098 r"""
2025-07-02 06:41:17.098 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.099 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.099 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.099 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.099
2025-07-02 06:41:17.099 Example:
2025-07-02 06:41:17.099
2025-07-02 06:41:17.099 >>> d = Differ()
2025-07-02 06:41:17.099 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.099 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.099 >>> print(''.join(results), end="")
2025-07-02 06:41:17.099 - abcDefghiJkl
2025-07-02 06:41:17.099 + abcdefGhijkl
2025-07-02 06:41:17.099 """
2025-07-02 06:41:17.099
2025-07-02 06:41:17.099 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.099 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.100 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.100 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.100 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.100
2025-07-02 06:41:17.100 # search for the pair that matches best without being identical
2025-07-02 06:41:17.100 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.100 # on junk -- unless we have to)
2025-07-02 06:41:17.100 for j in range(blo, bhi):
2025-07-02 06:41:17.100 bj = b[j]
2025-07-02 06:41:17.100 cruncher.set_seq2(bj)
2025-07-02 06:41:17.100 for i in range(alo, ahi):
2025-07-02 06:41:17.100 ai = a[i]
2025-07-02 06:41:17.100 if ai == bj:
2025-07-02 06:41:17.100 if eqi is None:
2025-07-02 06:41:17.100 eqi, eqj = i, j
2025-07-02 06:41:17.100 continue
2025-07-02 06:41:17.100 cruncher.set_seq1(ai)
2025-07-02 06:41:17.100 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.100 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.100 # compares by a factor of 3.
2025-07-02 06:41:17.101 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.101 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.101 # of the computation is cached by cruncher
2025-07-02 06:41:17.101 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.101 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.101 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.101 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.101 if best_ratio < cutoff:
2025-07-02 06:41:17.101 # no non-identical "pretty close" pair
2025-07-02 06:41:17.101 if eqi is None:
2025-07-02 06:41:17.101 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.101 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.101 return
2025-07-02 06:41:17.101 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.101 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.101 else:
2025-07-02 06:41:17.101 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.101 eqi = None
2025-07-02 06:41:17.101
2025-07-02 06:41:17.101 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.102 # identical
2025-07-02 06:41:17.102
2025-07-02 06:41:17.102 # pump out diffs from before the synch point
2025-07-02 06:41:17.102 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.102
2025-07-02 06:41:17.102 # do intraline marking on the synch pair
2025-07-02 06:41:17.102 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.102 if eqi is None:
2025-07-02 06:41:17.102 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.102 atags = btags = ""
2025-07-02 06:41:17.102 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.102 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.102 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.102 if tag == 'replace':
2025-07-02 06:41:17.102 atags += '^' * la
2025-07-02 06:41:17.102 btags += '^' * lb
2025-07-02 06:41:17.102 elif tag == 'delete':
2025-07-02 06:41:17.102 atags += '-' * la
2025-07-02 06:41:17.102 elif tag == 'insert':
2025-07-02 06:41:17.102 btags += '+' * lb
2025-07-02 06:41:17.103 elif tag == 'equal':
2025-07-02 06:41:17.103 atags += ' ' * la
2025-07-02 06:41:17.103 btags += ' ' * lb
2025-07-02 06:41:17.103 else:
2025-07-02 06:41:17.103 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.103 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.103 else:
2025-07-02 06:41:17.103 # the synch pair is identical
2025-07-02 06:41:17.103 yield ' ' + aelt
2025-07-02 06:41:17.103
2025-07-02 06:41:17.103 # pump out diffs from after the synch point
2025-07-02 06:41:17.103 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.103
2025-07-02 06:41:17.103 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.103 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.103
2025-07-02 06:41:17.103 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.103 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.103 alo = 171, ahi = 1101
2025-07-02 06:41:17.103 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.104 blo = 171, bhi = 1101
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.104 g = []
2025-07-02 06:41:17.104 if alo < ahi:
2025-07-02 06:41:17.104 if blo < bhi:
2025-07-02 06:41:17.104 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.104 else:
2025-07-02 06:41:17.104 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.104 elif blo < bhi:
2025-07-02 06:41:17.104 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 > yield from g
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.104 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.104 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.104 alo = 171, ahi = 1101
2025-07-02 06:41:17.104 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.105 blo = 171, bhi = 1101
2025-07-02 06:41:17.105
2025-07-02 06:41:17.105 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.105 r"""
2025-07-02 06:41:17.105 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.105 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.105 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.105 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.105
2025-07-02 06:41:17.105 Example:
2025-07-02 06:41:17.105
2025-07-02 06:41:17.105 >>> d = Differ()
2025-07-02 06:41:17.105 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.105 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.105 >>> print(''.join(results), end="")
2025-07-02 06:41:17.105 - abcDefghiJkl
2025-07-02 06:41:17.105 + abcdefGhijkl
2025-07-02 06:41:17.105 """
2025-07-02 06:41:17.106
2025-07-02 06:41:17.106 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.106 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.106 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.106 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.106 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.106
2025-07-02 06:41:17.106 # search for the pair that matches best without being identical
2025-07-02 06:41:17.106 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.106 # on junk -- unless we have to)
2025-07-02 06:41:17.106 for j in range(blo, bhi):
2025-07-02 06:41:17.106 bj = b[j]
2025-07-02 06:41:17.106 cruncher.set_seq2(bj)
2025-07-02 06:41:17.106 for i in range(alo, ahi):
2025-07-02 06:41:17.106 ai = a[i]
2025-07-02 06:41:17.106 if ai == bj:
2025-07-02 06:41:17.106 if eqi is None:
2025-07-02 06:41:17.106 eqi, eqj = i, j
2025-07-02 06:41:17.106 continue
2025-07-02 06:41:17.106 cruncher.set_seq1(ai)
2025-07-02 06:41:17.106 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.107 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.107 # compares by a factor of 3.
2025-07-02 06:41:17.107 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.107 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.107 # of the computation is cached by cruncher
2025-07-02 06:41:17.107 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.107 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.107 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.107 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.107 if best_ratio < cutoff:
2025-07-02 06:41:17.107 # no non-identical "pretty close" pair
2025-07-02 06:41:17.107 if eqi is None:
2025-07-02 06:41:17.107 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.107 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.107 return
2025-07-02 06:41:17.107 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.107 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.107 else:
2025-07-02 06:41:17.107 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.108 eqi = None
2025-07-02 06:41:17.108
2025-07-02 06:41:17.108 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.108 # identical
2025-07-02 06:41:17.108
2025-07-02 06:41:17.108 # pump out diffs from before the synch point
2025-07-02 06:41:17.108 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.108
2025-07-02 06:41:17.108 # do intraline marking on the synch pair
2025-07-02 06:41:17.108 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.108 if eqi is None:
2025-07-02 06:41:17.108 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.108 atags = btags = ""
2025-07-02 06:41:17.108 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.108 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.108 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.108 if tag == 'replace':
2025-07-02 06:41:17.108 atags += '^' * la
2025-07-02 06:41:17.108 btags += '^' * lb
2025-07-02 06:41:17.109 elif tag == 'delete':
2025-07-02 06:41:17.109 atags += '-' * la
2025-07-02 06:41:17.109 elif tag == 'insert':
2025-07-02 06:41:17.109 btags += '+' * lb
2025-07-02 06:41:17.109 elif tag == 'equal':
2025-07-02 06:41:17.109 atags += ' ' * la
2025-07-02 06:41:17.109 btags += ' ' * lb
2025-07-02 06:41:17.109 else:
2025-07-02 06:41:17.109 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.109 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.109 else:
2025-07-02 06:41:17.109 # the synch pair is identical
2025-07-02 06:41:17.109 yield ' ' + aelt
2025-07-02 06:41:17.109
2025-07-02 06:41:17.109 # pump out diffs from after the synch point
2025-07-02 06:41:17.109 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.109
2025-07-02 06:41:17.109 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.109 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.110 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.110 alo = 172, ahi = 1101
2025-07-02 06:41:17.110 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.110 blo = 172, bhi = 1101
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.110 g = []
2025-07-02 06:41:17.110 if alo < ahi:
2025-07-02 06:41:17.110 if blo < bhi:
2025-07-02 06:41:17.110 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.110 else:
2025-07-02 06:41:17.110 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.110 elif blo < bhi:
2025-07-02 06:41:17.110 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 > yield from g
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.111 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.111 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.111 alo = 172, ahi = 1101
2025-07-02 06:41:17.111 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.111 blo = 172, bhi = 1101
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.111 r"""
2025-07-02 06:41:17.111 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.111 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.111 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.111 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111 Example:
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111 >>> d = Differ()
2025-07-02 06:41:17.111 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.111 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.112 >>> print(''.join(results), end="")
2025-07-02 06:41:17.112 - abcDefghiJkl
2025-07-02 06:41:17.112 + abcdefGhijkl
2025-07-02 06:41:17.112 """
2025-07-02 06:41:17.112
2025-07-02 06:41:17.112 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.112 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.112 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.112 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.112 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.112
2025-07-02 06:41:17.112 # search for the pair that matches best without being identical
2025-07-02 06:41:17.112 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.112 # on junk -- unless we have to)
2025-07-02 06:41:17.112 for j in range(blo, bhi):
2025-07-02 06:41:17.112 bj = b[j]
2025-07-02 06:41:17.112 cruncher.set_seq2(bj)
2025-07-02 06:41:17.112 for i in range(alo, ahi):
2025-07-02 06:41:17.113 ai = a[i]
2025-07-02 06:41:17.113 if ai == bj:
2025-07-02 06:41:17.113 if eqi is None:
2025-07-02 06:41:17.113 eqi, eqj = i, j
2025-07-02 06:41:17.113 continue
2025-07-02 06:41:17.113 cruncher.set_seq1(ai)
2025-07-02 06:41:17.113 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.113 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.113 # compares by a factor of 3.
2025-07-02 06:41:17.113 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.113 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.113 # of the computation is cached by cruncher
2025-07-02 06:41:17.113 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.113 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.113 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.113 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.113 if best_ratio < cutoff:
2025-07-02 06:41:17.113 # no non-identical "pretty close" pair
2025-07-02 06:41:17.113 if eqi is None:
2025-07-02 06:41:17.113 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.113 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.114 return
2025-07-02 06:41:17.114 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.114 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.114 else:
2025-07-02 06:41:17.114 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.114 eqi = None
2025-07-02 06:41:17.114
2025-07-02 06:41:17.114 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.114 # identical
2025-07-02 06:41:17.114
2025-07-02 06:41:17.114 # pump out diffs from before the synch point
2025-07-02 06:41:17.114 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.114
2025-07-02 06:41:17.114 # do intraline marking on the synch pair
2025-07-02 06:41:17.114 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.114 if eqi is None:
2025-07-02 06:41:17.114 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.114 atags = btags = ""
2025-07-02 06:41:17.114 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.115 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.115 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.115 if tag == 'replace':
2025-07-02 06:41:17.115 atags += '^' * la
2025-07-02 06:41:17.115 btags += '^' * lb
2025-07-02 06:41:17.115 elif tag == 'delete':
2025-07-02 06:41:17.115 atags += '-' * la
2025-07-02 06:41:17.115 elif tag == 'insert':
2025-07-02 06:41:17.115 btags += '+' * lb
2025-07-02 06:41:17.115 elif tag == 'equal':
2025-07-02 06:41:17.115 atags += ' ' * la
2025-07-02 06:41:17.115 btags += ' ' * lb
2025-07-02 06:41:17.115 else:
2025-07-02 06:41:17.115 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.115 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.115 else:
2025-07-02 06:41:17.115 # the synch pair is identical
2025-07-02 06:41:17.115 yield ' ' + aelt
2025-07-02 06:41:17.115
2025-07-02 06:41:17.115 # pump out diffs from after the synch point
2025-07-02 06:41:17.116 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.116
2025-07-02 06:41:17.116 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.116 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.116
2025-07-02 06:41:17.116 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.116 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.116 alo = 173, ahi = 1101
2025-07-02 06:41:17.116 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.116 blo = 173, bhi = 1101
2025-07-02 06:41:17.116
2025-07-02 06:41:17.116 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.116 g = []
2025-07-02 06:41:17.116 if alo < ahi:
2025-07-02 06:41:17.116 if blo < bhi:
2025-07-02 06:41:17.116 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.116 else:
2025-07-02 06:41:17.116 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.116 elif blo < bhi:
2025-07-02 06:41:17.116 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 > yield from g
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.117 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.117 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.117 alo = 173, ahi = 1101
2025-07-02 06:41:17.117 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.117 blo = 173, bhi = 1101
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.117 r"""
2025-07-02 06:41:17.117 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.117 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.117 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.117 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.117
2025-07-02 06:41:17.118 Example:
2025-07-02 06:41:17.118
2025-07-02 06:41:17.118 >>> d = Differ()
2025-07-02 06:41:17.118 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.118 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.118 >>> print(''.join(results), end="")
2025-07-02 06:41:17.118 - abcDefghiJkl
2025-07-02 06:41:17.118 + abcdefGhijkl
2025-07-02 06:41:17.118 """
2025-07-02 06:41:17.118
2025-07-02 06:41:17.118 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.118 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.118 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.118 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.118 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.118
2025-07-02 06:41:17.118 # search for the pair that matches best without being identical
2025-07-02 06:41:17.118 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.119 # on junk -- unless we have to)
2025-07-02 06:41:17.119 for j in range(blo, bhi):
2025-07-02 06:41:17.119 bj = b[j]
2025-07-02 06:41:17.119 cruncher.set_seq2(bj)
2025-07-02 06:41:17.119 for i in range(alo, ahi):
2025-07-02 06:41:17.119 ai = a[i]
2025-07-02 06:41:17.119 if ai == bj:
2025-07-02 06:41:17.119 if eqi is None:
2025-07-02 06:41:17.119 eqi, eqj = i, j
2025-07-02 06:41:17.119 continue
2025-07-02 06:41:17.119 cruncher.set_seq1(ai)
2025-07-02 06:41:17.119 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.119 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.119 # compares by a factor of 3.
2025-07-02 06:41:17.119 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.119 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.119 # of the computation is cached by cruncher
2025-07-02 06:41:17.119 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.119 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.119 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.120 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.120 if best_ratio < cutoff:
2025-07-02 06:41:17.120 # no non-identical "pretty close" pair
2025-07-02 06:41:17.120 if eqi is None:
2025-07-02 06:41:17.120 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.120 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.120 return
2025-07-02 06:41:17.120 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.120 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.120 else:
2025-07-02 06:41:17.120 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.120 eqi = None
2025-07-02 06:41:17.120
2025-07-02 06:41:17.120 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.120 # identical
2025-07-02 06:41:17.120
2025-07-02 06:41:17.120 # pump out diffs from before the synch point
2025-07-02 06:41:17.120 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.120
2025-07-02 06:41:17.120 # do intraline marking on the synch pair
2025-07-02 06:41:17.120 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.121 if eqi is None:
2025-07-02 06:41:17.121 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.121 atags = btags = ""
2025-07-02 06:41:17.121 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.121 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.121 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.121 if tag == 'replace':
2025-07-02 06:41:17.121 atags += '^' * la
2025-07-02 06:41:17.121 btags += '^' * lb
2025-07-02 06:41:17.121 elif tag == 'delete':
2025-07-02 06:41:17.121 atags += '-' * la
2025-07-02 06:41:17.121 elif tag == 'insert':
2025-07-02 06:41:17.121 btags += '+' * lb
2025-07-02 06:41:17.121 elif tag == 'equal':
2025-07-02 06:41:17.121 atags += ' ' * la
2025-07-02 06:41:17.121 btags += ' ' * lb
2025-07-02 06:41:17.121 else:
2025-07-02 06:41:17.121 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.121 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.121 else:
2025-07-02 06:41:17.122 # the synch pair is identical
2025-07-02 06:41:17.122 yield ' ' + aelt
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122 # pump out diffs from after the synch point
2025-07-02 06:41:17.122 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.122 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.122 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.122 alo = 174, ahi = 1101
2025-07-02 06:41:17.122 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.122 blo = 174, bhi = 1101
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.122 g = []
2025-07-02 06:41:17.122 if alo < ahi:
2025-07-02 06:41:17.122 if blo < bhi:
2025-07-02 06:41:17.122 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.123 else:
2025-07-02 06:41:17.123 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.123 elif blo < bhi:
2025-07-02 06:41:17.123 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 > yield from g
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.123 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.123 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.123 alo = 174, ahi = 1101
2025-07-02 06:41:17.123 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.123 blo = 174, bhi = 1101
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.123 r"""
2025-07-02 06:41:17.123 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.123 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.124 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.124 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.124
2025-07-02 06:41:17.124 Example:
2025-07-02 06:41:17.124
2025-07-02 06:41:17.124 >>> d = Differ()
2025-07-02 06:41:17.124 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.124 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.124 >>> print(''.join(results), end="")
2025-07-02 06:41:17.124 - abcDefghiJkl
2025-07-02 06:41:17.124 + abcdefGhijkl
2025-07-02 06:41:17.124 """
2025-07-02 06:41:17.124
2025-07-02 06:41:17.124 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.124 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.124 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.124 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.125 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.125
2025-07-02 06:41:17.125 # search for the pair that matches best without being identical
2025-07-02 06:41:17.125 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.125 # on junk -- unless we have to)
2025-07-02 06:41:17.125 for j in range(blo, bhi):
2025-07-02 06:41:17.125 bj = b[j]
2025-07-02 06:41:17.125 cruncher.set_seq2(bj)
2025-07-02 06:41:17.125 for i in range(alo, ahi):
2025-07-02 06:41:17.125 ai = a[i]
2025-07-02 06:41:17.125 if ai == bj:
2025-07-02 06:41:17.125 if eqi is None:
2025-07-02 06:41:17.125 eqi, eqj = i, j
2025-07-02 06:41:17.125 continue
2025-07-02 06:41:17.125 cruncher.set_seq1(ai)
2025-07-02 06:41:17.125 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.125 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.126 # compares by a factor of 3.
2025-07-02 06:41:17.126 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.126 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.126 # of the computation is cached by cruncher
2025-07-02 06:41:17.126 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.126 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.126 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.126 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.126 if best_ratio < cutoff:
2025-07-02 06:41:17.126 # no non-identical "pretty close" pair
2025-07-02 06:41:17.126 if eqi is None:
2025-07-02 06:41:17.126 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.126 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.126 return
2025-07-02 06:41:17.126 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.126 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.126 else:
2025-07-02 06:41:17.126 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.126 eqi = None
2025-07-02 06:41:17.127
2025-07-02 06:41:17.127 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.127 # identical
2025-07-02 06:41:17.127
2025-07-02 06:41:17.127 # pump out diffs from before the synch point
2025-07-02 06:41:17.127 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.127
2025-07-02 06:41:17.127 # do intraline marking on the synch pair
2025-07-02 06:41:17.127 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.127 if eqi is None:
2025-07-02 06:41:17.127 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.127 atags = btags = ""
2025-07-02 06:41:17.127 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.127 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.127 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.127 if tag == 'replace':
2025-07-02 06:41:17.127 atags += '^' * la
2025-07-02 06:41:17.127 btags += '^' * lb
2025-07-02 06:41:17.127 elif tag == 'delete':
2025-07-02 06:41:17.128 atags += '-' * la
2025-07-02 06:41:17.128 elif tag == 'insert':
2025-07-02 06:41:17.128 btags += '+' * lb
2025-07-02 06:41:17.128 elif tag == 'equal':
2025-07-02 06:41:17.128 atags += ' ' * la
2025-07-02 06:41:17.128 btags += ' ' * lb
2025-07-02 06:41:17.128 else:
2025-07-02 06:41:17.128 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.128 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.128 else:
2025-07-02 06:41:17.128 # the synch pair is identical
2025-07-02 06:41:17.128 yield ' ' + aelt
2025-07-02 06:41:17.128
2025-07-02 06:41:17.128 # pump out diffs from after the synch point
2025-07-02 06:41:17.128 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.128
2025-07-02 06:41:17.128 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.128 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.128
2025-07-02 06:41:17.128 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.129 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.129 alo = 175, ahi = 1101
2025-07-02 06:41:17.129 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.129 blo = 175, bhi = 1101
2025-07-02 06:41:17.129
2025-07-02 06:41:17.129 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.129 g = []
2025-07-02 06:41:17.129 if alo < ahi:
2025-07-02 06:41:17.129 if blo < bhi:
2025-07-02 06:41:17.129 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.129 else:
2025-07-02 06:41:17.129 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.129 elif blo < bhi:
2025-07-02 06:41:17.129 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.129
2025-07-02 06:41:17.129 > yield from g
2025-07-02 06:41:17.129
2025-07-02 06:41:17.129 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.129 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.129
2025-07-02 06:41:17.130 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.130 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.130 alo = 175, ahi = 1101
2025-07-02 06:41:17.130 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.130 blo = 175, bhi = 1101
2025-07-02 06:41:17.130
2025-07-02 06:41:17.130 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.130 r"""
2025-07-02 06:41:17.130 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.130 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.130 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.130 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.130
2025-07-02 06:41:17.130 Example:
2025-07-02 06:41:17.130
2025-07-02 06:41:17.130 >>> d = Differ()
2025-07-02 06:41:17.130 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.130 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.130 >>> print(''.join(results), end="")
2025-07-02 06:41:17.131 - abcDefghiJkl
2025-07-02 06:41:17.131 + abcdefGhijkl
2025-07-02 06:41:17.131 """
2025-07-02 06:41:17.131
2025-07-02 06:41:17.131 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.131 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.131 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.131 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.131 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.131
2025-07-02 06:41:17.131 # search for the pair that matches best without being identical
2025-07-02 06:41:17.131 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.131 # on junk -- unless we have to)
2025-07-02 06:41:17.131 for j in range(blo, bhi):
2025-07-02 06:41:17.131 bj = b[j]
2025-07-02 06:41:17.131 cruncher.set_seq2(bj)
2025-07-02 06:41:17.131 for i in range(alo, ahi):
2025-07-02 06:41:17.131 ai = a[i]
2025-07-02 06:41:17.132 if ai == bj:
2025-07-02 06:41:17.132 if eqi is None:
2025-07-02 06:41:17.132 eqi, eqj = i, j
2025-07-02 06:41:17.132 continue
2025-07-02 06:41:17.132 cruncher.set_seq1(ai)
2025-07-02 06:41:17.132 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.132 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.132 # compares by a factor of 3.
2025-07-02 06:41:17.132 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.132 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.132 # of the computation is cached by cruncher
2025-07-02 06:41:17.132 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.132 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.132 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.132 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.132 if best_ratio < cutoff:
2025-07-02 06:41:17.132 # no non-identical "pretty close" pair
2025-07-02 06:41:17.132 if eqi is None:
2025-07-02 06:41:17.132 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.132 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.133 return
2025-07-02 06:41:17.133 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.133 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.133 else:
2025-07-02 06:41:17.133 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.133 eqi = None
2025-07-02 06:41:17.133
2025-07-02 06:41:17.133 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.133 # identical
2025-07-02 06:41:17.133
2025-07-02 06:41:17.133 # pump out diffs from before the synch point
2025-07-02 06:41:17.133 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.133
2025-07-02 06:41:17.133 # do intraline marking on the synch pair
2025-07-02 06:41:17.133 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.133 if eqi is None:
2025-07-02 06:41:17.133 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.133 atags = btags = ""
2025-07-02 06:41:17.133 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.133 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.134 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.134 if tag == 'replace':
2025-07-02 06:41:17.134 atags += '^' * la
2025-07-02 06:41:17.134 btags += '^' * lb
2025-07-02 06:41:17.134 elif tag == 'delete':
2025-07-02 06:41:17.134 atags += '-' * la
2025-07-02 06:41:17.134 elif tag == 'insert':
2025-07-02 06:41:17.134 btags += '+' * lb
2025-07-02 06:41:17.134 elif tag == 'equal':
2025-07-02 06:41:17.134 atags += ' ' * la
2025-07-02 06:41:17.134 btags += ' ' * lb
2025-07-02 06:41:17.134 else:
2025-07-02 06:41:17.134 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.134 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.134 else:
2025-07-02 06:41:17.134 # the synch pair is identical
2025-07-02 06:41:17.134 yield ' ' + aelt
2025-07-02 06:41:17.134
2025-07-02 06:41:17.135 # pump out diffs from after the synch point
2025-07-02 06:41:17.135 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.135
2025-07-02 06:41:17.135 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.135 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.135
2025-07-02 06:41:17.135 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.135 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.135 alo = 176, ahi = 1101
2025-07-02 06:41:17.135 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.135 blo = 176, bhi = 1101
2025-07-02 06:41:17.135
2025-07-02 06:41:17.135 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.135 g = []
2025-07-02 06:41:17.135 if alo < ahi:
2025-07-02 06:41:17.135 if blo < bhi:
2025-07-02 06:41:17.135 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.136 else:
2025-07-02 06:41:17.136 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.136 elif blo < bhi:
2025-07-02 06:41:17.136 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 > yield from g
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.136 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.136 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.136 alo = 176, ahi = 1101
2025-07-02 06:41:17.136 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.136 blo = 176, bhi = 1101
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.136 r"""
2025-07-02 06:41:17.136 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.137 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.137 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.137 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.137
2025-07-02 06:41:17.137 Example:
2025-07-02 06:41:17.137
2025-07-02 06:41:17.137 >>> d = Differ()
2025-07-02 06:41:17.137 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.137 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.137 >>> print(''.join(results), end="")
2025-07-02 06:41:17.137 - abcDefghiJkl
2025-07-02 06:41:17.137 + abcdefGhijkl
2025-07-02 06:41:17.137 """
2025-07-02 06:41:17.137
2025-07-02 06:41:17.137 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.137 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.137 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.138 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.138 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.138
2025-07-02 06:41:17.138 # search for the pair that matches best without being identical
2025-07-02 06:41:17.138 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.138 # on junk -- unless we have to)
2025-07-02 06:41:17.138 for j in range(blo, bhi):
2025-07-02 06:41:17.138 bj = b[j]
2025-07-02 06:41:17.138 cruncher.set_seq2(bj)
2025-07-02 06:41:17.138 for i in range(alo, ahi):
2025-07-02 06:41:17.138 ai = a[i]
2025-07-02 06:41:17.138 if ai == bj:
2025-07-02 06:41:17.138 if eqi is None:
2025-07-02 06:41:17.138 eqi, eqj = i, j
2025-07-02 06:41:17.138 continue
2025-07-02 06:41:17.138 cruncher.set_seq1(ai)
2025-07-02 06:41:17.138 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.138 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.138 # compares by a factor of 3.
2025-07-02 06:41:17.138 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.139 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.139 # of the computation is cached by cruncher
2025-07-02 06:41:17.139 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.139 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.139 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.139 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.139 if best_ratio < cutoff:
2025-07-02 06:41:17.139 # no non-identical "pretty close" pair
2025-07-02 06:41:17.139 if eqi is None:
2025-07-02 06:41:17.139 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.139 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.139 return
2025-07-02 06:41:17.139 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.139 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.139 else:
2025-07-02 06:41:17.139 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.139 eqi = None
2025-07-02 06:41:17.139
2025-07-02 06:41:17.140 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.140 # identical
2025-07-02 06:41:17.140
2025-07-02 06:41:17.140 # pump out diffs from before the synch point
2025-07-02 06:41:17.140 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.140
2025-07-02 06:41:17.140 # do intraline marking on the synch pair
2025-07-02 06:41:17.140 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.140 if eqi is None:
2025-07-02 06:41:17.140 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.140 atags = btags = ""
2025-07-02 06:41:17.140 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.140 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.140 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.140 if tag == 'replace':
2025-07-02 06:41:17.140 atags += '^' * la
2025-07-02 06:41:17.140 btags += '^' * lb
2025-07-02 06:41:17.140 elif tag == 'delete':
2025-07-02 06:41:17.140 atags += '-' * la
2025-07-02 06:41:17.141 elif tag == 'insert':
2025-07-02 06:41:17.141 btags += '+' * lb
2025-07-02 06:41:17.141 elif tag == 'equal':
2025-07-02 06:41:17.141 atags += ' ' * la
2025-07-02 06:41:17.141 btags += ' ' * lb
2025-07-02 06:41:17.141 else:
2025-07-02 06:41:17.141 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.141 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.141 else:
2025-07-02 06:41:17.141 # the synch pair is identical
2025-07-02 06:41:17.141 yield ' ' + aelt
2025-07-02 06:41:17.141
2025-07-02 06:41:17.141 # pump out diffs from after the synch point
2025-07-02 06:41:17.141 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.141
2025-07-02 06:41:17.141 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.141 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.141
2025-07-02 06:41:17.141 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.141 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.142 alo = 177, ahi = 1101
2025-07-02 06:41:17.142 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.142 blo = 177, bhi = 1101
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.142 g = []
2025-07-02 06:41:17.142 if alo < ahi:
2025-07-02 06:41:17.142 if blo < bhi:
2025-07-02 06:41:17.142 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.142 else:
2025-07-02 06:41:17.142 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.142 elif blo < bhi:
2025-07-02 06:41:17.142 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 > yield from g
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.142 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.143 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.143 alo = 177, ahi = 1101
2025-07-02 06:41:17.143 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.143 blo = 177, bhi = 1101
2025-07-02 06:41:17.143
2025-07-02 06:41:17.143 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.143 r"""
2025-07-02 06:41:17.143 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.143 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.143 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.143 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.143
2025-07-02 06:41:17.143 Example:
2025-07-02 06:41:17.143
2025-07-02 06:41:17.143 >>> d = Differ()
2025-07-02 06:41:17.143 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.143 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.143 >>> print(''.join(results), end="")
2025-07-02 06:41:17.144 - abcDefghiJkl
2025-07-02 06:41:17.144 + abcdefGhijkl
2025-07-02 06:41:17.144 """
2025-07-02 06:41:17.144
2025-07-02 06:41:17.144 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.144 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.144 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.144 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.144 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.144
2025-07-02 06:41:17.144 # search for the pair that matches best without being identical
2025-07-02 06:41:17.144 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.144 # on junk -- unless we have to)
2025-07-02 06:41:17.144 for j in range(blo, bhi):
2025-07-02 06:41:17.144 bj = b[j]
2025-07-02 06:41:17.144 cruncher.set_seq2(bj)
2025-07-02 06:41:17.144 for i in range(alo, ahi):
2025-07-02 06:41:17.145 ai = a[i]
2025-07-02 06:41:17.145 if ai == bj:
2025-07-02 06:41:17.145 if eqi is None:
2025-07-02 06:41:17.145 eqi, eqj = i, j
2025-07-02 06:41:17.145 continue
2025-07-02 06:41:17.145 cruncher.set_seq1(ai)
2025-07-02 06:41:17.145 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.145 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.145 # compares by a factor of 3.
2025-07-02 06:41:17.145 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.145 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.145 # of the computation is cached by cruncher
2025-07-02 06:41:17.145 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.145 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.145 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.145 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.145 if best_ratio < cutoff:
2025-07-02 06:41:17.145 # no non-identical "pretty close" pair
2025-07-02 06:41:17.145 if eqi is None:
2025-07-02 06:41:17.146 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.146 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.146 return
2025-07-02 06:41:17.146 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.146 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.146 else:
2025-07-02 06:41:17.146 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.146 eqi = None
2025-07-02 06:41:17.146
2025-07-02 06:41:17.146 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.146 # identical
2025-07-02 06:41:17.146
2025-07-02 06:41:17.146 # pump out diffs from before the synch point
2025-07-02 06:41:17.146 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.146
2025-07-02 06:41:17.146 # do intraline marking on the synch pair
2025-07-02 06:41:17.146 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.146 if eqi is None:
2025-07-02 06:41:17.146 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.146 atags = btags = ""
2025-07-02 06:41:17.146 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.147 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.147 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.147 if tag == 'replace':
2025-07-02 06:41:17.147 atags += '^' * la
2025-07-02 06:41:17.147 btags += '^' * lb
2025-07-02 06:41:17.147 elif tag == 'delete':
2025-07-02 06:41:17.147 atags += '-' * la
2025-07-02 06:41:17.147 elif tag == 'insert':
2025-07-02 06:41:17.147 btags += '+' * lb
2025-07-02 06:41:17.147 elif tag == 'equal':
2025-07-02 06:41:17.147 atags += ' ' * la
2025-07-02 06:41:17.147 btags += ' ' * lb
2025-07-02 06:41:17.147 else:
2025-07-02 06:41:17.147 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.147 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.147 else:
2025-07-02 06:41:17.147 # the synch pair is identical
2025-07-02 06:41:17.147 yield ' ' + aelt
2025-07-02 06:41:17.147
2025-07-02 06:41:17.147 # pump out diffs from after the synch point
2025-07-02 06:41:17.148 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.148
2025-07-02 06:41:17.148 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.148 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.148
2025-07-02 06:41:17.148 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.148 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.148 alo = 180, ahi = 1101
2025-07-02 06:41:17.148 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.148 blo = 180, bhi = 1101
2025-07-02 06:41:17.148
2025-07-02 06:41:17.148 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.148 g = []
2025-07-02 06:41:17.148 if alo < ahi:
2025-07-02 06:41:17.148 if blo < bhi:
2025-07-02 06:41:17.148 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.148 else:
2025-07-02 06:41:17.148 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.148 elif blo < bhi:
2025-07-02 06:41:17.148 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 > yield from g
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.149 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.149 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.149 alo = 180, ahi = 1101
2025-07-02 06:41:17.149 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.149 blo = 180, bhi = 1101
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.149 r"""
2025-07-02 06:41:17.149 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.149 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.149 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.149 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.149
2025-07-02 06:41:17.150 Example:
2025-07-02 06:41:17.150
2025-07-02 06:41:17.150 >>> d = Differ()
2025-07-02 06:41:17.150 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.150 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.150 >>> print(''.join(results), end="")
2025-07-02 06:41:17.150 - abcDefghiJkl
2025-07-02 06:41:17.150 + abcdefGhijkl
2025-07-02 06:41:17.150 """
2025-07-02 06:41:17.150
2025-07-02 06:41:17.150 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.150 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.150 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.150 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.150 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.150
2025-07-02 06:41:17.150 # search for the pair that matches best without being identical
2025-07-02 06:41:17.150 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.151 # on junk -- unless we have to)
2025-07-02 06:41:17.151 for j in range(blo, bhi):
2025-07-02 06:41:17.151 bj = b[j]
2025-07-02 06:41:17.151 cruncher.set_seq2(bj)
2025-07-02 06:41:17.151 for i in range(alo, ahi):
2025-07-02 06:41:17.151 ai = a[i]
2025-07-02 06:41:17.151 if ai == bj:
2025-07-02 06:41:17.151 if eqi is None:
2025-07-02 06:41:17.151 eqi, eqj = i, j
2025-07-02 06:41:17.151 continue
2025-07-02 06:41:17.151 cruncher.set_seq1(ai)
2025-07-02 06:41:17.151 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.151 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.151 # compares by a factor of 3.
2025-07-02 06:41:17.151 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.151 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.151 # of the computation is cached by cruncher
2025-07-02 06:41:17.151 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.151 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.151 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.152 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.152 if best_ratio < cutoff:
2025-07-02 06:41:17.152 # no non-identical "pretty close" pair
2025-07-02 06:41:17.152 if eqi is None:
2025-07-02 06:41:17.152 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.152 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.152 return
2025-07-02 06:41:17.152 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.152 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.152 else:
2025-07-02 06:41:17.152 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.152 eqi = None
2025-07-02 06:41:17.152
2025-07-02 06:41:17.152 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.152 # identical
2025-07-02 06:41:17.152
2025-07-02 06:41:17.152 # pump out diffs from before the synch point
2025-07-02 06:41:17.152 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.153
2025-07-02 06:41:17.153 # do intraline marking on the synch pair
2025-07-02 06:41:17.153 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.153 if eqi is None:
2025-07-02 06:41:17.153 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.153 atags = btags = ""
2025-07-02 06:41:17.153 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.153 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.153 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.153 if tag == 'replace':
2025-07-02 06:41:17.153 atags += '^' * la
2025-07-02 06:41:17.153 btags += '^' * lb
2025-07-02 06:41:17.153 elif tag == 'delete':
2025-07-02 06:41:17.153 atags += '-' * la
2025-07-02 06:41:17.153 elif tag == 'insert':
2025-07-02 06:41:17.153 btags += '+' * lb
2025-07-02 06:41:17.153 elif tag == 'equal':
2025-07-02 06:41:17.153 atags += ' ' * la
2025-07-02 06:41:17.153 btags += ' ' * lb
2025-07-02 06:41:17.154 else:
2025-07-02 06:41:17.154 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.154 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.154 else:
2025-07-02 06:41:17.154 # the synch pair is identical
2025-07-02 06:41:17.154 yield ' ' + aelt
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154 # pump out diffs from after the synch point
2025-07-02 06:41:17.154 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.154 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.154 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.154 alo = 181, ahi = 1101
2025-07-02 06:41:17.154 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.154 blo = 181, bhi = 1101
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.155 g = []
2025-07-02 06:41:17.155 if alo < ahi:
2025-07-02 06:41:17.155 if blo < bhi:
2025-07-02 06:41:17.155 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.155 else:
2025-07-02 06:41:17.155 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.155 elif blo < bhi:
2025-07-02 06:41:17.155 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.155
2025-07-02 06:41:17.155 > yield from g
2025-07-02 06:41:17.155
2025-07-02 06:41:17.155 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.155 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.155
2025-07-02 06:41:17.155 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.155 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.155 alo = 181, ahi = 1101
2025-07-02 06:41:17.155 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.156 blo = 181, bhi = 1101
2025-07-02 06:41:17.156
2025-07-02 06:41:17.156 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.156 r"""
2025-07-02 06:41:17.156 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.156 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.156 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.156 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.156
2025-07-02 06:41:17.156 Example:
2025-07-02 06:41:17.156
2025-07-02 06:41:17.156 >>> d = Differ()
2025-07-02 06:41:17.156 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.156 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.156 >>> print(''.join(results), end="")
2025-07-02 06:41:17.156 - abcDefghiJkl
2025-07-02 06:41:17.156 + abcdefGhijkl
2025-07-02 06:41:17.156 """
2025-07-02 06:41:17.157
2025-07-02 06:41:17.157 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.157 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.157 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.157 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.157 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.157
2025-07-02 06:41:17.157 # search for the pair that matches best without being identical
2025-07-02 06:41:17.157 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.157 # on junk -- unless we have to)
2025-07-02 06:41:17.157 for j in range(blo, bhi):
2025-07-02 06:41:17.157 bj = b[j]
2025-07-02 06:41:17.157 cruncher.set_seq2(bj)
2025-07-02 06:41:17.157 for i in range(alo, ahi):
2025-07-02 06:41:17.157 ai = a[i]
2025-07-02 06:41:17.157 if ai == bj:
2025-07-02 06:41:17.157 if eqi is None:
2025-07-02 06:41:17.157 eqi, eqj = i, j
2025-07-02 06:41:17.157 continue
2025-07-02 06:41:17.157 cruncher.set_seq1(ai)
2025-07-02 06:41:17.157 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.158 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.158 # compares by a factor of 3.
2025-07-02 06:41:17.158 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.158 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.158 # of the computation is cached by cruncher
2025-07-02 06:41:17.158 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.158 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.158 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.158 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.158 if best_ratio < cutoff:
2025-07-02 06:41:17.158 # no non-identical "pretty close" pair
2025-07-02 06:41:17.158 if eqi is None:
2025-07-02 06:41:17.158 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.158 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.158 return
2025-07-02 06:41:17.158 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.158 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.158 else:
2025-07-02 06:41:17.158 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.158 eqi = None
2025-07-02 06:41:17.159
2025-07-02 06:41:17.159 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.159 # identical
2025-07-02 06:41:17.159
2025-07-02 06:41:17.159 # pump out diffs from before the synch point
2025-07-02 06:41:17.159 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.159
2025-07-02 06:41:17.159 # do intraline marking on the synch pair
2025-07-02 06:41:17.159 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.159 if eqi is None:
2025-07-02 06:41:17.159 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.159 atags = btags = ""
2025-07-02 06:41:17.159 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.159 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.159 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.159 if tag == 'replace':
2025-07-02 06:41:17.159 atags += '^' * la
2025-07-02 06:41:17.159 btags += '^' * lb
2025-07-02 06:41:17.159 elif tag == 'delete':
2025-07-02 06:41:17.159 atags += '-' * la
2025-07-02 06:41:17.159 elif tag == 'insert':
2025-07-02 06:41:17.160 btags += '+' * lb
2025-07-02 06:41:17.160 elif tag == 'equal':
2025-07-02 06:41:17.160 atags += ' ' * la
2025-07-02 06:41:17.160 btags += ' ' * lb
2025-07-02 06:41:17.160 else:
2025-07-02 06:41:17.160 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.160 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.160 else:
2025-07-02 06:41:17.160 # the synch pair is identical
2025-07-02 06:41:17.160 yield ' ' + aelt
2025-07-02 06:41:17.160
2025-07-02 06:41:17.160 # pump out diffs from after the synch point
2025-07-02 06:41:17.160 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.160
2025-07-02 06:41:17.160 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.160 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.160
2025-07-02 06:41:17.160 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.160 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.160 alo = 182, ahi = 1101
2025-07-02 06:41:17.161 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.161 blo = 182, bhi = 1101
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.161 g = []
2025-07-02 06:41:17.161 if alo < ahi:
2025-07-02 06:41:17.161 if blo < bhi:
2025-07-02 06:41:17.161 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.161 else:
2025-07-02 06:41:17.161 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.161 elif blo < bhi:
2025-07-02 06:41:17.161 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 > yield from g
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.161 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.162 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.162 alo = 182, ahi = 1101
2025-07-02 06:41:17.162 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.162 blo = 182, bhi = 1101
2025-07-02 06:41:17.162
2025-07-02 06:41:17.162 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.162 r"""
2025-07-02 06:41:17.162 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.162 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.162 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.162 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.162
2025-07-02 06:41:17.162 Example:
2025-07-02 06:41:17.162
2025-07-02 06:41:17.162 >>> d = Differ()
2025-07-02 06:41:17.162 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.162 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.162 >>> print(''.join(results), end="")
2025-07-02 06:41:17.162 - abcDefghiJkl
2025-07-02 06:41:17.163 + abcdefGhijkl
2025-07-02 06:41:17.163 """
2025-07-02 06:41:17.163
2025-07-02 06:41:17.163 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.163 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.163 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.163 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.163 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.163
2025-07-02 06:41:17.163 # search for the pair that matches best without being identical
2025-07-02 06:41:17.163 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.163 # on junk -- unless we have to)
2025-07-02 06:41:17.163 for j in range(blo, bhi):
2025-07-02 06:41:17.163 bj = b[j]
2025-07-02 06:41:17.163 cruncher.set_seq2(bj)
2025-07-02 06:41:17.163 for i in range(alo, ahi):
2025-07-02 06:41:17.163 ai = a[i]
2025-07-02 06:41:17.163 if ai == bj:
2025-07-02 06:41:17.163 if eqi is None:
2025-07-02 06:41:17.164 eqi, eqj = i, j
2025-07-02 06:41:17.164 continue
2025-07-02 06:41:17.164 cruncher.set_seq1(ai)
2025-07-02 06:41:17.164 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.164 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.164 # compares by a factor of 3.
2025-07-02 06:41:17.164 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.164 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.164 # of the computation is cached by cruncher
2025-07-02 06:41:17.164 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.164 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.164 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.164 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.164 if best_ratio < cutoff:
2025-07-02 06:41:17.164 # no non-identical "pretty close" pair
2025-07-02 06:41:17.164 if eqi is None:
2025-07-02 06:41:17.164 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.164 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.164 return
2025-07-02 06:41:17.164 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.165 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.165 else:
2025-07-02 06:41:17.165 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.165 eqi = None
2025-07-02 06:41:17.165
2025-07-02 06:41:17.165 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.165 # identical
2025-07-02 06:41:17.165
2025-07-02 06:41:17.165 # pump out diffs from before the synch point
2025-07-02 06:41:17.165 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.165
2025-07-02 06:41:17.165 # do intraline marking on the synch pair
2025-07-02 06:41:17.165 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.165 if eqi is None:
2025-07-02 06:41:17.165 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.165 atags = btags = ""
2025-07-02 06:41:17.165 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.165 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.165 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.165 if tag == 'replace':
2025-07-02 06:41:17.166 atags += '^' * la
2025-07-02 06:41:17.166 btags += '^' * lb
2025-07-02 06:41:17.166 elif tag == 'delete':
2025-07-02 06:41:17.166 atags += '-' * la
2025-07-02 06:41:17.166 elif tag == 'insert':
2025-07-02 06:41:17.166 btags += '+' * lb
2025-07-02 06:41:17.166 elif tag == 'equal':
2025-07-02 06:41:17.166 atags += ' ' * la
2025-07-02 06:41:17.166 btags += ' ' * lb
2025-07-02 06:41:17.166 else:
2025-07-02 06:41:17.166 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.166 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.166 else:
2025-07-02 06:41:17.166 # the synch pair is identical
2025-07-02 06:41:17.166 yield ' ' + aelt
2025-07-02 06:41:17.166
2025-07-02 06:41:17.166 # pump out diffs from after the synch point
2025-07-02 06:41:17.166 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.166
2025-07-02 06:41:17.166 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.166 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.167 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.167 alo = 183, ahi = 1101
2025-07-02 06:41:17.167 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.167 blo = 183, bhi = 1101
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.167 g = []
2025-07-02 06:41:17.167 if alo < ahi:
2025-07-02 06:41:17.167 if blo < bhi:
2025-07-02 06:41:17.167 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.167 else:
2025-07-02 06:41:17.167 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.167 elif blo < bhi:
2025-07-02 06:41:17.167 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 > yield from g
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.168 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.168 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.168 alo = 183, ahi = 1101
2025-07-02 06:41:17.168 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.168 blo = 183, bhi = 1101
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.168 r"""
2025-07-02 06:41:17.168 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.168 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.168 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.168 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168 Example:
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168 >>> d = Differ()
2025-07-02 06:41:17.168 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.168 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.169 >>> print(''.join(results), end="")
2025-07-02 06:41:17.169 - abcDefghiJkl
2025-07-02 06:41:17.169 + abcdefGhijkl
2025-07-02 06:41:17.169 """
2025-07-02 06:41:17.169
2025-07-02 06:41:17.169 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.169 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.169 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.169 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.169 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.169
2025-07-02 06:41:17.169 # search for the pair that matches best without being identical
2025-07-02 06:41:17.169 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.169 # on junk -- unless we have to)
2025-07-02 06:41:17.169 for j in range(blo, bhi):
2025-07-02 06:41:17.169 bj = b[j]
2025-07-02 06:41:17.169 cruncher.set_seq2(bj)
2025-07-02 06:41:17.169 for i in range(alo, ahi):
2025-07-02 06:41:17.170 ai = a[i]
2025-07-02 06:41:17.170 if ai == bj:
2025-07-02 06:41:17.170 if eqi is None:
2025-07-02 06:41:17.170 eqi, eqj = i, j
2025-07-02 06:41:17.170 continue
2025-07-02 06:41:17.170 cruncher.set_seq1(ai)
2025-07-02 06:41:17.170 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.170 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.170 # compares by a factor of 3.
2025-07-02 06:41:17.170 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.170 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.170 # of the computation is cached by cruncher
2025-07-02 06:41:17.170 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.170 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.170 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.170 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.170 if best_ratio < cutoff:
2025-07-02 06:41:17.170 # no non-identical "pretty close" pair
2025-07-02 06:41:17.170 if eqi is None:
2025-07-02 06:41:17.171 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.171 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.171 return
2025-07-02 06:41:17.171 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.171 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.171 else:
2025-07-02 06:41:17.171 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.171 eqi = None
2025-07-02 06:41:17.171
2025-07-02 06:41:17.171 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.171 # identical
2025-07-02 06:41:17.171
2025-07-02 06:41:17.171 # pump out diffs from before the synch point
2025-07-02 06:41:17.171 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.171
2025-07-02 06:41:17.171 # do intraline marking on the synch pair
2025-07-02 06:41:17.171 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.171 if eqi is None:
2025-07-02 06:41:17.171 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.172 atags = btags = ""
2025-07-02 06:41:17.172 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.172 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.172 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.172 if tag == 'replace':
2025-07-02 06:41:17.172 atags += '^' * la
2025-07-02 06:41:17.172 btags += '^' * lb
2025-07-02 06:41:17.172 elif tag == 'delete':
2025-07-02 06:41:17.172 atags += '-' * la
2025-07-02 06:41:17.172 elif tag == 'insert':
2025-07-02 06:41:17.172 btags += '+' * lb
2025-07-02 06:41:17.172 elif tag == 'equal':
2025-07-02 06:41:17.172 atags += ' ' * la
2025-07-02 06:41:17.172 btags += ' ' * lb
2025-07-02 06:41:17.172 else:
2025-07-02 06:41:17.172 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.172 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.172 else:
2025-07-02 06:41:17.172 # the synch pair is identical
2025-07-02 06:41:17.172 yield ' ' + aelt
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173 # pump out diffs from after the synch point
2025-07-02 06:41:17.173 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.173 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.173 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.173 alo = 184, ahi = 1101
2025-07-02 06:41:17.173 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.173 blo = 184, bhi = 1101
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.173 g = []
2025-07-02 06:41:17.173 if alo < ahi:
2025-07-02 06:41:17.173 if blo < bhi:
2025-07-02 06:41:17.173 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.173 else:
2025-07-02 06:41:17.173 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.173 elif blo < bhi:
2025-07-02 06:41:17.174 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 > yield from g
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.174 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.174 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.174 alo = 184, ahi = 1101
2025-07-02 06:41:17.174 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.174 blo = 184, bhi = 1101
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.174 r"""
2025-07-02 06:41:17.174 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.174 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.174 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.174 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.174
2025-07-02 06:41:17.175 Example:
2025-07-02 06:41:17.175
2025-07-02 06:41:17.175 >>> d = Differ()
2025-07-02 06:41:17.175 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.175 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.175 >>> print(''.join(results), end="")
2025-07-02 06:41:17.175 - abcDefghiJkl
2025-07-02 06:41:17.175 + abcdefGhijkl
2025-07-02 06:41:17.175 """
2025-07-02 06:41:17.175
2025-07-02 06:41:17.175 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.175 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.175 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.175 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.175 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.175
2025-07-02 06:41:17.175 # search for the pair that matches best without being identical
2025-07-02 06:41:17.175 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.176 # on junk -- unless we have to)
2025-07-02 06:41:17.176 for j in range(blo, bhi):
2025-07-02 06:41:17.176 bj = b[j]
2025-07-02 06:41:17.176 cruncher.set_seq2(bj)
2025-07-02 06:41:17.176 for i in range(alo, ahi):
2025-07-02 06:41:17.176 ai = a[i]
2025-07-02 06:41:17.176 if ai == bj:
2025-07-02 06:41:17.176 if eqi is None:
2025-07-02 06:41:17.176 eqi, eqj = i, j
2025-07-02 06:41:17.176 continue
2025-07-02 06:41:17.176 cruncher.set_seq1(ai)
2025-07-02 06:41:17.176 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.176 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.176 # compares by a factor of 3.
2025-07-02 06:41:17.176 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.176 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.176 # of the computation is cached by cruncher
2025-07-02 06:41:17.176 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.176 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.176 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.176 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.177 if best_ratio < cutoff:
2025-07-02 06:41:17.177 # no non-identical "pretty close" pair
2025-07-02 06:41:17.177 if eqi is None:
2025-07-02 06:41:17.177 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.177 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.177 return
2025-07-02 06:41:17.177 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.177 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.177 else:
2025-07-02 06:41:17.177 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.177 eqi = None
2025-07-02 06:41:17.177
2025-07-02 06:41:17.177 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.177 # identical
2025-07-02 06:41:17.177
2025-07-02 06:41:17.177 # pump out diffs from before the synch point
2025-07-02 06:41:17.177 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.177
2025-07-02 06:41:17.177 # do intraline marking on the synch pair
2025-07-02 06:41:17.177 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.178 if eqi is None:
2025-07-02 06:41:17.178 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.178 atags = btags = ""
2025-07-02 06:41:17.178 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.178 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.178 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.178 if tag == 'replace':
2025-07-02 06:41:17.178 atags += '^' * la
2025-07-02 06:41:17.178 btags += '^' * lb
2025-07-02 06:41:17.178 elif tag == 'delete':
2025-07-02 06:41:17.178 atags += '-' * la
2025-07-02 06:41:17.178 elif tag == 'insert':
2025-07-02 06:41:17.178 btags += '+' * lb
2025-07-02 06:41:17.178 elif tag == 'equal':
2025-07-02 06:41:17.178 atags += ' ' * la
2025-07-02 06:41:17.178 btags += ' ' * lb
2025-07-02 06:41:17.178 else:
2025-07-02 06:41:17.178 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.179 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.179 else:
2025-07-02 06:41:17.179 # the synch pair is identical
2025-07-02 06:41:17.179 yield ' ' + aelt
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179 # pump out diffs from after the synch point
2025-07-02 06:41:17.179 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.179 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.179 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.179 alo = 185, ahi = 1101
2025-07-02 06:41:17.179 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.179 blo = 185, bhi = 1101
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.179 g = []
2025-07-02 06:41:17.180 if alo < ahi:
2025-07-02 06:41:17.180 if blo < bhi:
2025-07-02 06:41:17.180 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.180 else:
2025-07-02 06:41:17.180 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.180 elif blo < bhi:
2025-07-02 06:41:17.180 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 > yield from g
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.180 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.180 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.180 alo = 185, ahi = 1101
2025-07-02 06:41:17.180 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.180 blo = 185, bhi = 1101
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.181 r"""
2025-07-02 06:41:17.181 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.181 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.181 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.181 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.181
2025-07-02 06:41:17.181 Example:
2025-07-02 06:41:17.181
2025-07-02 06:41:17.181 >>> d = Differ()
2025-07-02 06:41:17.181 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.181 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.181 >>> print(''.join(results), end="")
2025-07-02 06:41:17.181 - abcDefghiJkl
2025-07-02 06:41:17.181 + abcdefGhijkl
2025-07-02 06:41:17.181 """
2025-07-02 06:41:17.181
2025-07-02 06:41:17.181 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.181 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.181 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.182 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.182 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.182
2025-07-02 06:41:17.182 # search for the pair that matches best without being identical
2025-07-02 06:41:17.182 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.182 # on junk -- unless we have to)
2025-07-02 06:41:17.182 for j in range(blo, bhi):
2025-07-02 06:41:17.182 bj = b[j]
2025-07-02 06:41:17.182 cruncher.set_seq2(bj)
2025-07-02 06:41:17.182 for i in range(alo, ahi):
2025-07-02 06:41:17.182 ai = a[i]
2025-07-02 06:41:17.182 if ai == bj:
2025-07-02 06:41:17.182 if eqi is None:
2025-07-02 06:41:17.182 eqi, eqj = i, j
2025-07-02 06:41:17.182 continue
2025-07-02 06:41:17.182 cruncher.set_seq1(ai)
2025-07-02 06:41:17.182 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.182 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.182 # compares by a factor of 3.
2025-07-02 06:41:17.182 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.183 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.183 # of the computation is cached by cruncher
2025-07-02 06:41:17.183 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.183 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.183 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.183 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.183 if best_ratio < cutoff:
2025-07-02 06:41:17.183 # no non-identical "pretty close" pair
2025-07-02 06:41:17.183 if eqi is None:
2025-07-02 06:41:17.183 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.183 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.183 return
2025-07-02 06:41:17.183 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.183 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.183 else:
2025-07-02 06:41:17.183 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.183 eqi = None
2025-07-02 06:41:17.183
2025-07-02 06:41:17.183 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.183 # identical
2025-07-02 06:41:17.184
2025-07-02 06:41:17.184 # pump out diffs from before the synch point
2025-07-02 06:41:17.184 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.184
2025-07-02 06:41:17.184 # do intraline marking on the synch pair
2025-07-02 06:41:17.184 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.184 if eqi is None:
2025-07-02 06:41:17.184 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.184 atags = btags = ""
2025-07-02 06:41:17.184 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.184 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.184 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.184 if tag == 'replace':
2025-07-02 06:41:17.184 atags += '^' * la
2025-07-02 06:41:17.184 btags += '^' * lb
2025-07-02 06:41:17.184 elif tag == 'delete':
2025-07-02 06:41:17.184 atags += '-' * la
2025-07-02 06:41:17.184 elif tag == 'insert':
2025-07-02 06:41:17.184 btags += '+' * lb
2025-07-02 06:41:17.184 elif tag == 'equal':
2025-07-02 06:41:17.184 atags += ' ' * la
2025-07-02 06:41:17.185 btags += ' ' * lb
2025-07-02 06:41:17.185 else:
2025-07-02 06:41:17.185 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.185 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.185 else:
2025-07-02 06:41:17.185 # the synch pair is identical
2025-07-02 06:41:17.185 yield ' ' + aelt
2025-07-02 06:41:17.185
2025-07-02 06:41:17.185 # pump out diffs from after the synch point
2025-07-02 06:41:17.185 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.185
2025-07-02 06:41:17.185 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.185 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.185
2025-07-02 06:41:17.185 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.185 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.185 alo = 186, ahi = 1101
2025-07-02 06:41:17.185 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.185 blo = 186, bhi = 1101
2025-07-02 06:41:17.185
2025-07-02 06:41:17.186 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.186 g = []
2025-07-02 06:41:17.186 if alo < ahi:
2025-07-02 06:41:17.186 if blo < bhi:
2025-07-02 06:41:17.186 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.186 else:
2025-07-02 06:41:17.186 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.186 elif blo < bhi:
2025-07-02 06:41:17.186 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.186
2025-07-02 06:41:17.186 > yield from g
2025-07-02 06:41:17.186
2025-07-02 06:41:17.186 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.186 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.186
2025-07-02 06:41:17.186 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.186 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.186 alo = 186, ahi = 1101
2025-07-02 06:41:17.186 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.187 blo = 186, bhi = 1101
2025-07-02 06:41:17.187
2025-07-02 06:41:17.187 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.187 r"""
2025-07-02 06:41:17.187 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.187 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.187 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.187 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.187
2025-07-02 06:41:17.187 Example:
2025-07-02 06:41:17.187
2025-07-02 06:41:17.187 >>> d = Differ()
2025-07-02 06:41:17.187 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.187 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.187 >>> print(''.join(results), end="")
2025-07-02 06:41:17.187 - abcDefghiJkl
2025-07-02 06:41:17.188 + abcdefGhijkl
2025-07-02 06:41:17.188 """
2025-07-02 06:41:17.188
2025-07-02 06:41:17.188 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.188 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.188 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.188 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.188 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.188
2025-07-02 06:41:17.188 # search for the pair that matches best without being identical
2025-07-02 06:41:17.188 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.188 # on junk -- unless we have to)
2025-07-02 06:41:17.188 for j in range(blo, bhi):
2025-07-02 06:41:17.188 bj = b[j]
2025-07-02 06:41:17.188 cruncher.set_seq2(bj)
2025-07-02 06:41:17.188 for i in range(alo, ahi):
2025-07-02 06:41:17.188 ai = a[i]
2025-07-02 06:41:17.188 if ai == bj:
2025-07-02 06:41:17.189 if eqi is None:
2025-07-02 06:41:17.189 eqi, eqj = i, j
2025-07-02 06:41:17.189 continue
2025-07-02 06:41:17.189 cruncher.set_seq1(ai)
2025-07-02 06:41:17.189 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.189 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.189 # compares by a factor of 3.
2025-07-02 06:41:17.189 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.189 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.189 # of the computation is cached by cruncher
2025-07-02 06:41:17.189 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.189 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.189 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.189 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.189 if best_ratio < cutoff:
2025-07-02 06:41:17.189 # no non-identical "pretty close" pair
2025-07-02 06:41:17.189 if eqi is None:
2025-07-02 06:41:17.189 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.189 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.189 return
2025-07-02 06:41:17.190 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.190 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.190 else:
2025-07-02 06:41:17.190 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.190 eqi = None
2025-07-02 06:41:17.190
2025-07-02 06:41:17.190 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.190 # identical
2025-07-02 06:41:17.190
2025-07-02 06:41:17.190 # pump out diffs from before the synch point
2025-07-02 06:41:17.190 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.190
2025-07-02 06:41:17.190 # do intraline marking on the synch pair
2025-07-02 06:41:17.190 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.190 if eqi is None:
2025-07-02 06:41:17.190 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.190 atags = btags = ""
2025-07-02 06:41:17.190 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.190 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.190 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.190 if tag == 'replace':
2025-07-02 06:41:17.191 atags += '^' * la
2025-07-02 06:41:17.191 btags += '^' * lb
2025-07-02 06:41:17.191 elif tag == 'delete':
2025-07-02 06:41:17.191 atags += '-' * la
2025-07-02 06:41:17.191 elif tag == 'insert':
2025-07-02 06:41:17.191 btags += '+' * lb
2025-07-02 06:41:17.191 elif tag == 'equal':
2025-07-02 06:41:17.191 atags += ' ' * la
2025-07-02 06:41:17.191 btags += ' ' * lb
2025-07-02 06:41:17.191 else:
2025-07-02 06:41:17.191 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.191 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.191 else:
2025-07-02 06:41:17.191 # the synch pair is identical
2025-07-02 06:41:17.191 yield ' ' + aelt
2025-07-02 06:41:17.191
2025-07-02 06:41:17.191 # pump out diffs from after the synch point
2025-07-02 06:41:17.191 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.191
2025-07-02 06:41:17.191 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.192 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.192
2025-07-02 06:41:17.192 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.192 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.192 alo = 187, ahi = 1101
2025-07-02 06:41:17.192 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.192 blo = 187, bhi = 1101
2025-07-02 06:41:17.192
2025-07-02 06:41:17.192 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.192 g = []
2025-07-02 06:41:17.192 if alo < ahi:
2025-07-02 06:41:17.192 if blo < bhi:
2025-07-02 06:41:17.192 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.192 else:
2025-07-02 06:41:17.192 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.192 elif blo < bhi:
2025-07-02 06:41:17.192 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.192
2025-07-02 06:41:17.192 > yield from g
2025-07-02 06:41:17.192
2025-07-02 06:41:17.193 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.193 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.193 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.193 alo = 187, ahi = 1101
2025-07-02 06:41:17.193 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.193 blo = 187, bhi = 1101
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.193 r"""
2025-07-02 06:41:17.193 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.193 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.193 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.193 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193 Example:
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193 >>> d = Differ()
2025-07-02 06:41:17.193 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.193 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.194 >>> print(''.join(results), end="")
2025-07-02 06:41:17.194 - abcDefghiJkl
2025-07-02 06:41:17.194 + abcdefGhijkl
2025-07-02 06:41:17.194 """
2025-07-02 06:41:17.194
2025-07-02 06:41:17.194 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.194 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.194 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.194 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.194 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.194
2025-07-02 06:41:17.194 # search for the pair that matches best without being identical
2025-07-02 06:41:17.194 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.194 # on junk -- unless we have to)
2025-07-02 06:41:17.194 for j in range(blo, bhi):
2025-07-02 06:41:17.194 bj = b[j]
2025-07-02 06:41:17.194 cruncher.set_seq2(bj)
2025-07-02 06:41:17.194 for i in range(alo, ahi):
2025-07-02 06:41:17.195 ai = a[i]
2025-07-02 06:41:17.195 if ai == bj:
2025-07-02 06:41:17.195 if eqi is None:
2025-07-02 06:41:17.195 eqi, eqj = i, j
2025-07-02 06:41:17.195 continue
2025-07-02 06:41:17.195 cruncher.set_seq1(ai)
2025-07-02 06:41:17.195 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.195 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.195 # compares by a factor of 3.
2025-07-02 06:41:17.195 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.195 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.195 # of the computation is cached by cruncher
2025-07-02 06:41:17.195 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.195 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.195 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.195 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.195 if best_ratio < cutoff:
2025-07-02 06:41:17.195 # no non-identical "pretty close" pair
2025-07-02 06:41:17.195 if eqi is None:
2025-07-02 06:41:17.196 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.196 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.196 return
2025-07-02 06:41:17.196 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.196 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.196 else:
2025-07-02 06:41:17.196 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.196 eqi = None
2025-07-02 06:41:17.196
2025-07-02 06:41:17.196 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.196 # identical
2025-07-02 06:41:17.196
2025-07-02 06:41:17.196 # pump out diffs from before the synch point
2025-07-02 06:41:17.196 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.196
2025-07-02 06:41:17.196 # do intraline marking on the synch pair
2025-07-02 06:41:17.196 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.196 if eqi is None:
2025-07-02 06:41:17.196 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.196 atags = btags = ""
2025-07-02 06:41:17.197 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.197 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.197 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.197 if tag == 'replace':
2025-07-02 06:41:17.197 atags += '^' * la
2025-07-02 06:41:17.197 btags += '^' * lb
2025-07-02 06:41:17.197 elif tag == 'delete':
2025-07-02 06:41:17.197 atags += '-' * la
2025-07-02 06:41:17.197 elif tag == 'insert':
2025-07-02 06:41:17.197 btags += '+' * lb
2025-07-02 06:41:17.197 elif tag == 'equal':
2025-07-02 06:41:17.197 atags += ' ' * la
2025-07-02 06:41:17.197 btags += ' ' * lb
2025-07-02 06:41:17.197 else:
2025-07-02 06:41:17.197 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.197 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.197 else:
2025-07-02 06:41:17.197 # the synch pair is identical
2025-07-02 06:41:17.197 yield ' ' + aelt
2025-07-02 06:41:17.197
2025-07-02 06:41:17.198 # pump out diffs from after the synch point
2025-07-02 06:41:17.198 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.198
2025-07-02 06:41:17.198 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.198
2025-07-02 06:41:17.198 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.198 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.198 alo = 188, ahi = 1101
2025-07-02 06:41:17.198 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.198 blo = 188, bhi = 1101
2025-07-02 06:41:17.198
2025-07-02 06:41:17.198 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.198 g = []
2025-07-02 06:41:17.198 if alo < ahi:
2025-07-02 06:41:17.198 if blo < bhi:
2025-07-02 06:41:17.198 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.198 else:
2025-07-02 06:41:17.198 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.198 elif blo < bhi:
2025-07-02 06:41:17.199 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 > yield from g
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.199 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.199 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.199 alo = 188, ahi = 1101
2025-07-02 06:41:17.199 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.199 blo = 188, bhi = 1101
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.199 r"""
2025-07-02 06:41:17.199 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.199 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.199 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.199 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.199
2025-07-02 06:41:17.200 Example:
2025-07-02 06:41:17.200
2025-07-02 06:41:17.200 >>> d = Differ()
2025-07-02 06:41:17.200 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.200 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.200 >>> print(''.join(results), end="")
2025-07-02 06:41:17.200 - abcDefghiJkl
2025-07-02 06:41:17.200 + abcdefGhijkl
2025-07-02 06:41:17.200 """
2025-07-02 06:41:17.200
2025-07-02 06:41:17.200 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.200 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.200 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.200 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.200 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.200
2025-07-02 06:41:17.200 # search for the pair that matches best without being identical
2025-07-02 06:41:17.200 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.200 # on junk -- unless we have to)
2025-07-02 06:41:17.201 for j in range(blo, bhi):
2025-07-02 06:41:17.201 bj = b[j]
2025-07-02 06:41:17.201 cruncher.set_seq2(bj)
2025-07-02 06:41:17.201 for i in range(alo, ahi):
2025-07-02 06:41:17.201 ai = a[i]
2025-07-02 06:41:17.201 if ai == bj:
2025-07-02 06:41:17.201 if eqi is None:
2025-07-02 06:41:17.201 eqi, eqj = i, j
2025-07-02 06:41:17.201 continue
2025-07-02 06:41:17.201 cruncher.set_seq1(ai)
2025-07-02 06:41:17.201 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.201 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.201 # compares by a factor of 3.
2025-07-02 06:41:17.201 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.201 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.201 # of the computation is cached by cruncher
2025-07-02 06:41:17.201 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.201 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.201 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.201 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.202 if best_ratio < cutoff:
2025-07-02 06:41:17.202 # no non-identical "pretty close" pair
2025-07-02 06:41:17.202 if eqi is None:
2025-07-02 06:41:17.202 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.202 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.202 return
2025-07-02 06:41:17.202 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.202 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.202 else:
2025-07-02 06:41:17.202 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.202 eqi = None
2025-07-02 06:41:17.202
2025-07-02 06:41:17.202 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.202 # identical
2025-07-02 06:41:17.202
2025-07-02 06:41:17.202 # pump out diffs from before the synch point
2025-07-02 06:41:17.202 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.202
2025-07-02 06:41:17.202 # do intraline marking on the synch pair
2025-07-02 06:41:17.202 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.203 if eqi is None:
2025-07-02 06:41:17.203 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.203 atags = btags = ""
2025-07-02 06:41:17.203 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.203 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.203 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.203 if tag == 'replace':
2025-07-02 06:41:17.203 atags += '^' * la
2025-07-02 06:41:17.203 btags += '^' * lb
2025-07-02 06:41:17.203 elif tag == 'delete':
2025-07-02 06:41:17.203 atags += '-' * la
2025-07-02 06:41:17.203 elif tag == 'insert':
2025-07-02 06:41:17.203 btags += '+' * lb
2025-07-02 06:41:17.203 elif tag == 'equal':
2025-07-02 06:41:17.203 atags += ' ' * la
2025-07-02 06:41:17.203 btags += ' ' * lb
2025-07-02 06:41:17.203 else:
2025-07-02 06:41:17.203 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.204 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.204 else:
2025-07-02 06:41:17.204 # the synch pair is identical
2025-07-02 06:41:17.204 yield ' ' + aelt
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204 # pump out diffs from after the synch point
2025-07-02 06:41:17.204 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.204 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.204 alo = 189, ahi = 1101
2025-07-02 06:41:17.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.204 blo = 189, bhi = 1101
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.205 g = []
2025-07-02 06:41:17.205 if alo < ahi:
2025-07-02 06:41:17.205 if blo < bhi:
2025-07-02 06:41:17.205 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.205 else:
2025-07-02 06:41:17.205 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.205 elif blo < bhi:
2025-07-02 06:41:17.205 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.205
2025-07-02 06:41:17.205 > yield from g
2025-07-02 06:41:17.205
2025-07-02 06:41:17.205 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.205 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.205
2025-07-02 06:41:17.205 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.205 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.205 alo = 189, ahi = 1101
2025-07-02 06:41:17.205 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.205 blo = 189, bhi = 1101
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.206 r"""
2025-07-02 06:41:17.206 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.206 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.206 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.206 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206 Example:
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206 >>> d = Differ()
2025-07-02 06:41:17.206 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.206 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.206 >>> print(''.join(results), end="")
2025-07-02 06:41:17.206 - abcDefghiJkl
2025-07-02 06:41:17.206 + abcdefGhijkl
2025-07-02 06:41:17.206 """
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.207 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.207 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.207 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.207 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.207
2025-07-02 06:41:17.207 # search for the pair that matches best without being identical
2025-07-02 06:41:17.207 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.207 # on junk -- unless we have to)
2025-07-02 06:41:17.207 for j in range(blo, bhi):
2025-07-02 06:41:17.207 bj = b[j]
2025-07-02 06:41:17.207 cruncher.set_seq2(bj)
2025-07-02 06:41:17.207 for i in range(alo, ahi):
2025-07-02 06:41:17.207 ai = a[i]
2025-07-02 06:41:17.207 if ai == bj:
2025-07-02 06:41:17.207 if eqi is None:
2025-07-02 06:41:17.207 eqi, eqj = i, j
2025-07-02 06:41:17.207 continue
2025-07-02 06:41:17.207 cruncher.set_seq1(ai)
2025-07-02 06:41:17.207 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.207 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.208 # compares by a factor of 3.
2025-07-02 06:41:17.208 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.208 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.208 # of the computation is cached by cruncher
2025-07-02 06:41:17.208 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.208 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.208 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.208 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.208 if best_ratio < cutoff:
2025-07-02 06:41:17.208 # no non-identical "pretty close" pair
2025-07-02 06:41:17.208 if eqi is None:
2025-07-02 06:41:17.208 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.208 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.208 return
2025-07-02 06:41:17.208 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.208 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.208 else:
2025-07-02 06:41:17.208 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.208 eqi = None
2025-07-02 06:41:17.208
2025-07-02 06:41:17.209 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.209 # identical
2025-07-02 06:41:17.209
2025-07-02 06:41:17.209 # pump out diffs from before the synch point
2025-07-02 06:41:17.209 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.209
2025-07-02 06:41:17.209 # do intraline marking on the synch pair
2025-07-02 06:41:17.209 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.209 if eqi is None:
2025-07-02 06:41:17.209 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.209 atags = btags = ""
2025-07-02 06:41:17.209 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.209 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.209 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.209 if tag == 'replace':
2025-07-02 06:41:17.209 atags += '^' * la
2025-07-02 06:41:17.209 btags += '^' * lb
2025-07-02 06:41:17.209 elif tag == 'delete':
2025-07-02 06:41:17.209 atags += '-' * la
2025-07-02 06:41:17.209 elif tag == 'insert':
2025-07-02 06:41:17.209 btags += '+' * lb
2025-07-02 06:41:17.210 elif tag == 'equal':
2025-07-02 06:41:17.210 atags += ' ' * la
2025-07-02 06:41:17.210 btags += ' ' * lb
2025-07-02 06:41:17.210 else:
2025-07-02 06:41:17.210 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.210 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.210 else:
2025-07-02 06:41:17.210 # the synch pair is identical
2025-07-02 06:41:17.210 yield ' ' + aelt
2025-07-02 06:41:17.210
2025-07-02 06:41:17.210 # pump out diffs from after the synch point
2025-07-02 06:41:17.210 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.210
2025-07-02 06:41:17.210 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.210 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.210
2025-07-02 06:41:17.210 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.210 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.210 alo = 190, ahi = 1101
2025-07-02 06:41:17.210 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.211 blo = 190, bhi = 1101
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.211 g = []
2025-07-02 06:41:17.211 if alo < ahi:
2025-07-02 06:41:17.211 if blo < bhi:
2025-07-02 06:41:17.211 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.211 else:
2025-07-02 06:41:17.211 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.211 elif blo < bhi:
2025-07-02 06:41:17.211 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 > yield from g
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.211 alo = 190, ahi = 1101
2025-07-02 06:41:17.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.212 blo = 190, bhi = 1101
2025-07-02 06:41:17.212
2025-07-02 06:41:17.212 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.212 r"""
2025-07-02 06:41:17.212 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.212 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.212 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.212 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.212
2025-07-02 06:41:17.212 Example:
2025-07-02 06:41:17.212
2025-07-02 06:41:17.212 >>> d = Differ()
2025-07-02 06:41:17.212 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.212 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.212 >>> print(''.join(results), end="")
2025-07-02 06:41:17.212 - abcDefghiJkl
2025-07-02 06:41:17.212 + abcdefGhijkl
2025-07-02 06:41:17.213 """
2025-07-02 06:41:17.213
2025-07-02 06:41:17.213 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.213 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.213 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.213 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.213 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.213
2025-07-02 06:41:17.213 # search for the pair that matches best without being identical
2025-07-02 06:41:17.213 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.213 # on junk -- unless we have to)
2025-07-02 06:41:17.213 for j in range(blo, bhi):
2025-07-02 06:41:17.213 bj = b[j]
2025-07-02 06:41:17.213 cruncher.set_seq2(bj)
2025-07-02 06:41:17.213 for i in range(alo, ahi):
2025-07-02 06:41:17.213 ai = a[i]
2025-07-02 06:41:17.213 if ai == bj:
2025-07-02 06:41:17.213 if eqi is None:
2025-07-02 06:41:17.213 eqi, eqj = i, j
2025-07-02 06:41:17.213 continue
2025-07-02 06:41:17.214 cruncher.set_seq1(ai)
2025-07-02 06:41:17.214 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.214 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.214 # compares by a factor of 3.
2025-07-02 06:41:17.214 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.214 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.214 # of the computation is cached by cruncher
2025-07-02 06:41:17.214 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.214 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.214 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.214 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.214 if best_ratio < cutoff:
2025-07-02 06:41:17.214 # no non-identical "pretty close" pair
2025-07-02 06:41:17.214 if eqi is None:
2025-07-02 06:41:17.214 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.214 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.214 return
2025-07-02 06:41:17.214 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.214 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.215 else:
2025-07-02 06:41:17.215 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.215 eqi = None
2025-07-02 06:41:17.215
2025-07-02 06:41:17.215 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.215 # identical
2025-07-02 06:41:17.215
2025-07-02 06:41:17.215 # pump out diffs from before the synch point
2025-07-02 06:41:17.215 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.215
2025-07-02 06:41:17.215 # do intraline marking on the synch pair
2025-07-02 06:41:17.215 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.215 if eqi is None:
2025-07-02 06:41:17.215 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.215 atags = btags = ""
2025-07-02 06:41:17.215 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.215 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.215 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.215 if tag == 'replace':
2025-07-02 06:41:17.215 atags += '^' * la
2025-07-02 06:41:17.215 btags += '^' * lb
2025-07-02 06:41:17.216 elif tag == 'delete':
2025-07-02 06:41:17.216 atags += '-' * la
2025-07-02 06:41:17.216 elif tag == 'insert':
2025-07-02 06:41:17.216 btags += '+' * lb
2025-07-02 06:41:17.216 elif tag == 'equal':
2025-07-02 06:41:17.216 atags += ' ' * la
2025-07-02 06:41:17.216 btags += ' ' * lb
2025-07-02 06:41:17.216 else:
2025-07-02 06:41:17.216 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.216 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.216 else:
2025-07-02 06:41:17.216 # the synch pair is identical
2025-07-02 06:41:17.216 yield ' ' + aelt
2025-07-02 06:41:17.216
2025-07-02 06:41:17.216 # pump out diffs from after the synch point
2025-07-02 06:41:17.216 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.216
2025-07-02 06:41:17.216 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.216 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.216
2025-07-02 06:41:17.216 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.217 alo = 191, ahi = 1101
2025-07-02 06:41:17.217 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.217 blo = 191, bhi = 1101
2025-07-02 06:41:17.217
2025-07-02 06:41:17.217 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.217 g = []
2025-07-02 06:41:17.217 if alo < ahi:
2025-07-02 06:41:17.217 if blo < bhi:
2025-07-02 06:41:17.217 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.217 else:
2025-07-02 06:41:17.217 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.217 elif blo < bhi:
2025-07-02 06:41:17.217 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.217
2025-07-02 06:41:17.217 > yield from g
2025-07-02 06:41:17.217
2025-07-02 06:41:17.217 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.217
2025-07-02 06:41:17.218 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.218 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.218 alo = 191, ahi = 1101
2025-07-02 06:41:17.218 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.218 blo = 191, bhi = 1101
2025-07-02 06:41:17.218
2025-07-02 06:41:17.218 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.218 r"""
2025-07-02 06:41:17.218 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.218 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.218 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.218 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.218
2025-07-02 06:41:17.218 Example:
2025-07-02 06:41:17.218
2025-07-02 06:41:17.218 >>> d = Differ()
2025-07-02 06:41:17.218 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.218 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.218 >>> print(''.join(results), end="")
2025-07-02 06:41:17.218 - abcDefghiJkl
2025-07-02 06:41:17.219 + abcdefGhijkl
2025-07-02 06:41:17.219 """
2025-07-02 06:41:17.219
2025-07-02 06:41:17.219 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.219 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.219 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.219 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.219 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.219
2025-07-02 06:41:17.219 # search for the pair that matches best without being identical
2025-07-02 06:41:17.219 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.219 # on junk -- unless we have to)
2025-07-02 06:41:17.219 for j in range(blo, bhi):
2025-07-02 06:41:17.219 bj = b[j]
2025-07-02 06:41:17.219 cruncher.set_seq2(bj)
2025-07-02 06:41:17.219 for i in range(alo, ahi):
2025-07-02 06:41:17.220 ai = a[i]
2025-07-02 06:41:17.220 if ai == bj:
2025-07-02 06:41:17.220 if eqi is None:
2025-07-02 06:41:17.220 eqi, eqj = i, j
2025-07-02 06:41:17.220 continue
2025-07-02 06:41:17.220 cruncher.set_seq1(ai)
2025-07-02 06:41:17.220 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.220 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.220 # compares by a factor of 3.
2025-07-02 06:41:17.220 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.220 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.220 # of the computation is cached by cruncher
2025-07-02 06:41:17.220 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.220 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.220 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.220 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.220 if best_ratio < cutoff:
2025-07-02 06:41:17.220 # no non-identical "pretty close" pair
2025-07-02 06:41:17.220 if eqi is None:
2025-07-02 06:41:17.220 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.221 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.221 return
2025-07-02 06:41:17.221 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.221 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.221 else:
2025-07-02 06:41:17.221 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.221 eqi = None
2025-07-02 06:41:17.221
2025-07-02 06:41:17.221 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.221 # identical
2025-07-02 06:41:17.221
2025-07-02 06:41:17.221 # pump out diffs from before the synch point
2025-07-02 06:41:17.221 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.221
2025-07-02 06:41:17.221 # do intraline marking on the synch pair
2025-07-02 06:41:17.221 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.221 if eqi is None:
2025-07-02 06:41:17.221 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.222 atags = btags = ""
2025-07-02 06:41:17.222 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.222 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.222 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.222 if tag == 'replace':
2025-07-02 06:41:17.222 atags += '^' * la
2025-07-02 06:41:17.222 btags += '^' * lb
2025-07-02 06:41:17.222 elif tag == 'delete':
2025-07-02 06:41:17.222 atags += '-' * la
2025-07-02 06:41:17.222 elif tag == 'insert':
2025-07-02 06:41:17.222 btags += '+' * lb
2025-07-02 06:41:17.222 elif tag == 'equal':
2025-07-02 06:41:17.222 atags += ' ' * la
2025-07-02 06:41:17.222 btags += ' ' * lb
2025-07-02 06:41:17.222 else:
2025-07-02 06:41:17.222 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.222 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.222 else:
2025-07-02 06:41:17.222 # the synch pair is identical
2025-07-02 06:41:17.222 yield ' ' + aelt
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223 # pump out diffs from after the synch point
2025-07-02 06:41:17.223 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.223 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.223 alo = 192, ahi = 1101
2025-07-02 06:41:17.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.223 blo = 192, bhi = 1101
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.223 g = []
2025-07-02 06:41:17.223 if alo < ahi:
2025-07-02 06:41:17.223 if blo < bhi:
2025-07-02 06:41:17.223 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.223 else:
2025-07-02 06:41:17.223 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.224 elif blo < bhi:
2025-07-02 06:41:17.224 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 > yield from g
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.224 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.224 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.224 alo = 192, ahi = 1101
2025-07-02 06:41:17.224 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.224 blo = 192, bhi = 1101
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.224 r"""
2025-07-02 06:41:17.224 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.224 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.224 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.224 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225 Example:
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225 >>> d = Differ()
2025-07-02 06:41:17.225 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.225 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.225 >>> print(''.join(results), end="")
2025-07-02 06:41:17.225 - abcDefghiJkl
2025-07-02 06:41:17.225 + abcdefGhijkl
2025-07-02 06:41:17.225 """
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.225 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.225 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.225 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.225 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225 # search for the pair that matches best without being identical
2025-07-02 06:41:17.225 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.226 # on junk -- unless we have to)
2025-07-02 06:41:17.226 for j in range(blo, bhi):
2025-07-02 06:41:17.226 bj = b[j]
2025-07-02 06:41:17.226 cruncher.set_seq2(bj)
2025-07-02 06:41:17.226 for i in range(alo, ahi):
2025-07-02 06:41:17.226 ai = a[i]
2025-07-02 06:41:17.226 if ai == bj:
2025-07-02 06:41:17.226 if eqi is None:
2025-07-02 06:41:17.226 eqi, eqj = i, j
2025-07-02 06:41:17.226 continue
2025-07-02 06:41:17.226 cruncher.set_seq1(ai)
2025-07-02 06:41:17.226 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.226 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.226 # compares by a factor of 3.
2025-07-02 06:41:17.226 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.226 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.226 # of the computation is cached by cruncher
2025-07-02 06:41:17.226 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.226 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.226 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.227 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.227 if best_ratio < cutoff:
2025-07-02 06:41:17.227 # no non-identical "pretty close" pair
2025-07-02 06:41:17.227 if eqi is None:
2025-07-02 06:41:17.227 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.227 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.227 return
2025-07-02 06:41:17.227 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.227 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.227 else:
2025-07-02 06:41:17.227 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.227 eqi = None
2025-07-02 06:41:17.227
2025-07-02 06:41:17.227 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.227 # identical
2025-07-02 06:41:17.227
2025-07-02 06:41:17.227 # pump out diffs from before the synch point
2025-07-02 06:41:17.227 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.227
2025-07-02 06:41:17.227 # do intraline marking on the synch pair
2025-07-02 06:41:17.227 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.228 if eqi is None:
2025-07-02 06:41:17.228 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.228 atags = btags = ""
2025-07-02 06:41:17.228 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.228 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.228 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.228 if tag == 'replace':
2025-07-02 06:41:17.228 atags += '^' * la
2025-07-02 06:41:17.228 btags += '^' * lb
2025-07-02 06:41:17.228 elif tag == 'delete':
2025-07-02 06:41:17.228 atags += '-' * la
2025-07-02 06:41:17.228 elif tag == 'insert':
2025-07-02 06:41:17.228 btags += '+' * lb
2025-07-02 06:41:17.228 elif tag == 'equal':
2025-07-02 06:41:17.228 atags += ' ' * la
2025-07-02 06:41:17.228 btags += ' ' * lb
2025-07-02 06:41:17.228 else:
2025-07-02 06:41:17.228 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.228 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.228 else:
2025-07-02 06:41:17.229 # the synch pair is identical
2025-07-02 06:41:17.229 yield ' ' + aelt
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229 # pump out diffs from after the synch point
2025-07-02 06:41:17.229 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.229 alo = 193, ahi = 1101
2025-07-02 06:41:17.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.229 blo = 193, bhi = 1101
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.229 g = []
2025-07-02 06:41:17.229 if alo < ahi:
2025-07-02 06:41:17.229 if blo < bhi:
2025-07-02 06:41:17.230 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.230 else:
2025-07-02 06:41:17.230 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.230 elif blo < bhi:
2025-07-02 06:41:17.230 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 > yield from g
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.230 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.230 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.230 alo = 193, ahi = 1101
2025-07-02 06:41:17.230 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.230 blo = 193, bhi = 1101
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.230 r"""
2025-07-02 06:41:17.230 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.231 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.231 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.231 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.231
2025-07-02 06:41:17.231 Example:
2025-07-02 06:41:17.231
2025-07-02 06:41:17.231 >>> d = Differ()
2025-07-02 06:41:17.231 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.231 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.231 >>> print(''.join(results), end="")
2025-07-02 06:41:17.231 - abcDefghiJkl
2025-07-02 06:41:17.231 + abcdefGhijkl
2025-07-02 06:41:17.231 """
2025-07-02 06:41:17.231
2025-07-02 06:41:17.231 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.231 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.231 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.232 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.232 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.232
2025-07-02 06:41:17.232 # search for the pair that matches best without being identical
2025-07-02 06:41:17.232 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.232 # on junk -- unless we have to)
2025-07-02 06:41:17.232 for j in range(blo, bhi):
2025-07-02 06:41:17.232 bj = b[j]
2025-07-02 06:41:17.232 cruncher.set_seq2(bj)
2025-07-02 06:41:17.232 for i in range(alo, ahi):
2025-07-02 06:41:17.232 ai = a[i]
2025-07-02 06:41:17.232 if ai == bj:
2025-07-02 06:41:17.232 if eqi is None:
2025-07-02 06:41:17.232 eqi, eqj = i, j
2025-07-02 06:41:17.232 continue
2025-07-02 06:41:17.232 cruncher.set_seq1(ai)
2025-07-02 06:41:17.232 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.232 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.232 # compares by a factor of 3.
2025-07-02 06:41:17.232 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.232 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.233 # of the computation is cached by cruncher
2025-07-02 06:41:17.233 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.233 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.233 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.233 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.233 if best_ratio < cutoff:
2025-07-02 06:41:17.233 # no non-identical "pretty close" pair
2025-07-02 06:41:17.233 if eqi is None:
2025-07-02 06:41:17.233 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.233 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.233 return
2025-07-02 06:41:17.233 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.233 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.233 else:
2025-07-02 06:41:17.233 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.233 eqi = None
2025-07-02 06:41:17.233
2025-07-02 06:41:17.233 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.233 # identical
2025-07-02 06:41:17.233
2025-07-02 06:41:17.234 # pump out diffs from before the synch point
2025-07-02 06:41:17.234 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.234
2025-07-02 06:41:17.234 # do intraline marking on the synch pair
2025-07-02 06:41:17.234 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.234 if eqi is None:
2025-07-02 06:41:17.234 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.234 atags = btags = ""
2025-07-02 06:41:17.234 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.234 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.234 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.234 if tag == 'replace':
2025-07-02 06:41:17.234 atags += '^' * la
2025-07-02 06:41:17.234 btags += '^' * lb
2025-07-02 06:41:17.234 elif tag == 'delete':
2025-07-02 06:41:17.234 atags += '-' * la
2025-07-02 06:41:17.234 elif tag == 'insert':
2025-07-02 06:41:17.234 btags += '+' * lb
2025-07-02 06:41:17.234 elif tag == 'equal':
2025-07-02 06:41:17.234 atags += ' ' * la
2025-07-02 06:41:17.234 btags += ' ' * lb
2025-07-02 06:41:17.235 else:
2025-07-02 06:41:17.235 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.235 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.235 else:
2025-07-02 06:41:17.235 # the synch pair is identical
2025-07-02 06:41:17.235 yield ' ' + aelt
2025-07-02 06:41:17.235
2025-07-02 06:41:17.235 # pump out diffs from after the synch point
2025-07-02 06:41:17.235 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.235
2025-07-02 06:41:17.235 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.235
2025-07-02 06:41:17.235 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.235 alo = 194, ahi = 1101
2025-07-02 06:41:17.235 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.236 blo = 194, bhi = 1101
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.236 g = []
2025-07-02 06:41:17.236 if alo < ahi:
2025-07-02 06:41:17.236 if blo < bhi:
2025-07-02 06:41:17.236 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.236 else:
2025-07-02 06:41:17.236 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.236 elif blo < bhi:
2025-07-02 06:41:17.236 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 > yield from g
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.236 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.236 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.236 alo = 194, ahi = 1101
2025-07-02 06:41:17.237 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.237 blo = 194, bhi = 1101
2025-07-02 06:41:17.237
2025-07-02 06:41:17.237 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.237 r"""
2025-07-02 06:41:17.237 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.237 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.237 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.237 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.237
2025-07-02 06:41:17.237 Example:
2025-07-02 06:41:17.237
2025-07-02 06:41:17.237 >>> d = Differ()
2025-07-02 06:41:17.237 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.237 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.237 >>> print(''.join(results), end="")
2025-07-02 06:41:17.237 - abcDefghiJkl
2025-07-02 06:41:17.237 + abcdefGhijkl
2025-07-02 06:41:17.238 """
2025-07-02 06:41:17.238
2025-07-02 06:41:17.238 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.238 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.238 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.238 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.238 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.238
2025-07-02 06:41:17.238 # search for the pair that matches best without being identical
2025-07-02 06:41:17.238 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.238 # on junk -- unless we have to)
2025-07-02 06:41:17.238 for j in range(blo, bhi):
2025-07-02 06:41:17.238 bj = b[j]
2025-07-02 06:41:17.238 cruncher.set_seq2(bj)
2025-07-02 06:41:17.238 for i in range(alo, ahi):
2025-07-02 06:41:17.238 ai = a[i]
2025-07-02 06:41:17.238 if ai == bj:
2025-07-02 06:41:17.238 if eqi is None:
2025-07-02 06:41:17.239 eqi, eqj = i, j
2025-07-02 06:41:17.239 continue
2025-07-02 06:41:17.239 cruncher.set_seq1(ai)
2025-07-02 06:41:17.239 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.239 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.239 # compares by a factor of 3.
2025-07-02 06:41:17.239 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.239 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.239 # of the computation is cached by cruncher
2025-07-02 06:41:17.239 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.239 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.239 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.239 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.239 if best_ratio < cutoff:
2025-07-02 06:41:17.239 # no non-identical "pretty close" pair
2025-07-02 06:41:17.239 if eqi is None:
2025-07-02 06:41:17.239 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.239 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.239 return
2025-07-02 06:41:17.240 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.240 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.240 else:
2025-07-02 06:41:17.240 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.240 eqi = None
2025-07-02 06:41:17.240
2025-07-02 06:41:17.240 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.240 # identical
2025-07-02 06:41:17.240
2025-07-02 06:41:17.240 # pump out diffs from before the synch point
2025-07-02 06:41:17.240 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.240
2025-07-02 06:41:17.240 # do intraline marking on the synch pair
2025-07-02 06:41:17.240 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.240 if eqi is None:
2025-07-02 06:41:17.240 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.240 atags = btags = ""
2025-07-02 06:41:17.240 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.240 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.240 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.241 if tag == 'replace':
2025-07-02 06:41:17.241 atags += '^' * la
2025-07-02 06:41:17.241 btags += '^' * lb
2025-07-02 06:41:17.241 elif tag == 'delete':
2025-07-02 06:41:17.241 atags += '-' * la
2025-07-02 06:41:17.241 elif tag == 'insert':
2025-07-02 06:41:17.241 btags += '+' * lb
2025-07-02 06:41:17.241 elif tag == 'equal':
2025-07-02 06:41:17.241 atags += ' ' * la
2025-07-02 06:41:17.241 btags += ' ' * lb
2025-07-02 06:41:17.241 else:
2025-07-02 06:41:17.241 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.241 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.241 else:
2025-07-02 06:41:17.241 # the synch pair is identical
2025-07-02 06:41:17.241 yield ' ' + aelt
2025-07-02 06:41:17.241
2025-07-02 06:41:17.241 # pump out diffs from after the synch point
2025-07-02 06:41:17.241 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.241
2025-07-02 06:41:17.241 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.242 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.242
2025-07-02 06:41:17.242 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.242 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.242 alo = 195, ahi = 1101
2025-07-02 06:41:17.242 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.242 blo = 195, bhi = 1101
2025-07-02 06:41:17.242
2025-07-02 06:41:17.242 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.242 g = []
2025-07-02 06:41:17.242 if alo < ahi:
2025-07-02 06:41:17.242 if blo < bhi:
2025-07-02 06:41:17.242 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.242 else:
2025-07-02 06:41:17.242 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.242 elif blo < bhi:
2025-07-02 06:41:17.242 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.242
2025-07-02 06:41:17.242 > yield from g
2025-07-02 06:41:17.242
2025-07-02 06:41:17.243 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.243 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.243 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.243 alo = 195, ahi = 1101
2025-07-02 06:41:17.243 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.243 blo = 195, bhi = 1101
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.243 r"""
2025-07-02 06:41:17.243 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.243 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.243 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.243 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243 Example:
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243 >>> d = Differ()
2025-07-02 06:41:17.244 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.244 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.244 >>> print(''.join(results), end="")
2025-07-02 06:41:17.244 - abcDefghiJkl
2025-07-02 06:41:17.244 + abcdefGhijkl
2025-07-02 06:41:17.244 """
2025-07-02 06:41:17.244
2025-07-02 06:41:17.244 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.244 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.244 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.244 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.244 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.244
2025-07-02 06:41:17.244 # search for the pair that matches best without being identical
2025-07-02 06:41:17.244 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.244 # on junk -- unless we have to)
2025-07-02 06:41:17.244 for j in range(blo, bhi):
2025-07-02 06:41:17.244 bj = b[j]
2025-07-02 06:41:17.245 cruncher.set_seq2(bj)
2025-07-02 06:41:17.245 for i in range(alo, ahi):
2025-07-02 06:41:17.245 ai = a[i]
2025-07-02 06:41:17.245 if ai == bj:
2025-07-02 06:41:17.245 if eqi is None:
2025-07-02 06:41:17.245 eqi, eqj = i, j
2025-07-02 06:41:17.245 continue
2025-07-02 06:41:17.245 cruncher.set_seq1(ai)
2025-07-02 06:41:17.245 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.245 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.245 # compares by a factor of 3.
2025-07-02 06:41:17.245 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.245 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.245 # of the computation is cached by cruncher
2025-07-02 06:41:17.245 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.245 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.245 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.245 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.245 if best_ratio < cutoff:
2025-07-02 06:41:17.245 # no non-identical "pretty close" pair
2025-07-02 06:41:17.246 if eqi is None:
2025-07-02 06:41:17.246 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.246 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.246 return
2025-07-02 06:41:17.246 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.246 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.246 else:
2025-07-02 06:41:17.246 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.246 eqi = None
2025-07-02 06:41:17.246
2025-07-02 06:41:17.246 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.246 # identical
2025-07-02 06:41:17.246
2025-07-02 06:41:17.246 # pump out diffs from before the synch point
2025-07-02 06:41:17.246 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.246
2025-07-02 06:41:17.246 # do intraline marking on the synch pair
2025-07-02 06:41:17.246 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.246 if eqi is None:
2025-07-02 06:41:17.246 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.247 atags = btags = ""
2025-07-02 06:41:17.247 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.247 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.247 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.247 if tag == 'replace':
2025-07-02 06:41:17.247 atags += '^' * la
2025-07-02 06:41:17.247 btags += '^' * lb
2025-07-02 06:41:17.247 elif tag == 'delete':
2025-07-02 06:41:17.247 atags += '-' * la
2025-07-02 06:41:17.247 elif tag == 'insert':
2025-07-02 06:41:17.247 btags += '+' * lb
2025-07-02 06:41:17.247 elif tag == 'equal':
2025-07-02 06:41:17.247 atags += ' ' * la
2025-07-02 06:41:17.247 btags += ' ' * lb
2025-07-02 06:41:17.247 else:
2025-07-02 06:41:17.247 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.247 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.247 else:
2025-07-02 06:41:17.247 # the synch pair is identical
2025-07-02 06:41:17.248 yield ' ' + aelt
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248 # pump out diffs from after the synch point
2025-07-02 06:41:17.248 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.248 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.248 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.248 alo = 196, ahi = 1101
2025-07-02 06:41:17.248 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.248 blo = 196, bhi = 1101
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.248 g = []
2025-07-02 06:41:17.248 if alo < ahi:
2025-07-02 06:41:17.248 if blo < bhi:
2025-07-02 06:41:17.248 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.249 else:
2025-07-02 06:41:17.249 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.249 elif blo < bhi:
2025-07-02 06:41:17.249 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 > yield from g
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.249 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.249 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.249 alo = 196, ahi = 1101
2025-07-02 06:41:17.249 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.249 blo = 196, bhi = 1101
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.249 r"""
2025-07-02 06:41:17.249 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.249 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.250 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.250 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.250
2025-07-02 06:41:17.250 Example:
2025-07-02 06:41:17.250
2025-07-02 06:41:17.250 >>> d = Differ()
2025-07-02 06:41:17.250 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.250 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.250 >>> print(''.join(results), end="")
2025-07-02 06:41:17.250 - abcDefghiJkl
2025-07-02 06:41:17.250 + abcdefGhijkl
2025-07-02 06:41:17.250 """
2025-07-02 06:41:17.250
2025-07-02 06:41:17.250 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.250 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.250 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.250 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.250 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.251
2025-07-02 06:41:17.251 # search for the pair that matches best without being identical
2025-07-02 06:41:17.251 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.251 # on junk -- unless we have to)
2025-07-02 06:41:17.251 for j in range(blo, bhi):
2025-07-02 06:41:17.251 bj = b[j]
2025-07-02 06:41:17.251 cruncher.set_seq2(bj)
2025-07-02 06:41:17.251 for i in range(alo, ahi):
2025-07-02 06:41:17.251 ai = a[i]
2025-07-02 06:41:17.251 if ai == bj:
2025-07-02 06:41:17.251 if eqi is None:
2025-07-02 06:41:17.251 eqi, eqj = i, j
2025-07-02 06:41:17.251 continue
2025-07-02 06:41:17.251 cruncher.set_seq1(ai)
2025-07-02 06:41:17.251 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.251 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.251 # compares by a factor of 3.
2025-07-02 06:41:17.251 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.252 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.252 # of the computation is cached by cruncher
2025-07-02 06:41:17.252 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.252 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.252 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.252 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.252 if best_ratio < cutoff:
2025-07-02 06:41:17.252 # no non-identical "pretty close" pair
2025-07-02 06:41:17.252 if eqi is None:
2025-07-02 06:41:17.252 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.252 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.252 return
2025-07-02 06:41:17.252 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.252 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.252 else:
2025-07-02 06:41:17.252 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.252 eqi = None
2025-07-02 06:41:17.252
2025-07-02 06:41:17.252 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.253 # identical
2025-07-02 06:41:17.253
2025-07-02 06:41:17.253 # pump out diffs from before the synch point
2025-07-02 06:41:17.253 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.253
2025-07-02 06:41:17.253 # do intraline marking on the synch pair
2025-07-02 06:41:17.253 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.253 if eqi is None:
2025-07-02 06:41:17.253 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.253 atags = btags = ""
2025-07-02 06:41:17.253 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.253 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.253 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.253 if tag == 'replace':
2025-07-02 06:41:17.253 atags += '^' * la
2025-07-02 06:41:17.253 btags += '^' * lb
2025-07-02 06:41:17.253 elif tag == 'delete':
2025-07-02 06:41:17.253 atags += '-' * la
2025-07-02 06:41:17.253 elif tag == 'insert':
2025-07-02 06:41:17.253 btags += '+' * lb
2025-07-02 06:41:17.253 elif tag == 'equal':
2025-07-02 06:41:17.254 atags += ' ' * la
2025-07-02 06:41:17.254 btags += ' ' * lb
2025-07-02 06:41:17.254 else:
2025-07-02 06:41:17.254 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.254 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.254 else:
2025-07-02 06:41:17.254 # the synch pair is identical
2025-07-02 06:41:17.254 yield ' ' + aelt
2025-07-02 06:41:17.254
2025-07-02 06:41:17.254 # pump out diffs from after the synch point
2025-07-02 06:41:17.254 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.254
2025-07-02 06:41:17.254 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.254 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.254
2025-07-02 06:41:17.254 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.254 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.254 alo = 197, ahi = 1101
2025-07-02 06:41:17.254 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.254 blo = 197, bhi = 1101
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.255 g = []
2025-07-02 06:41:17.255 if alo < ahi:
2025-07-02 06:41:17.255 if blo < bhi:
2025-07-02 06:41:17.255 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.255 else:
2025-07-02 06:41:17.255 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.255 elif blo < bhi:
2025-07-02 06:41:17.255 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 > yield from g
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.255 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.255 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.255 alo = 197, ahi = 1101
2025-07-02 06:41:17.255 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.256 blo = 197, bhi = 1101
2025-07-02 06:41:17.256
2025-07-02 06:41:17.256 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.256 r"""
2025-07-02 06:41:17.256 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.256 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.256 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.256 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.256
2025-07-02 06:41:17.256 Example:
2025-07-02 06:41:17.256
2025-07-02 06:41:17.256 >>> d = Differ()
2025-07-02 06:41:17.256 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.256 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.256 >>> print(''.join(results), end="")
2025-07-02 06:41:17.256 - abcDefghiJkl
2025-07-02 06:41:17.256 + abcdefGhijkl
2025-07-02 06:41:17.257 """
2025-07-02 06:41:17.257
2025-07-02 06:41:17.257 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.257 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.257 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.257 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.257 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.257
2025-07-02 06:41:17.257 # search for the pair that matches best without being identical
2025-07-02 06:41:17.257 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.257 # on junk -- unless we have to)
2025-07-02 06:41:17.257 for j in range(blo, bhi):
2025-07-02 06:41:17.257 bj = b[j]
2025-07-02 06:41:17.257 cruncher.set_seq2(bj)
2025-07-02 06:41:17.257 for i in range(alo, ahi):
2025-07-02 06:41:17.257 ai = a[i]
2025-07-02 06:41:17.257 if ai == bj:
2025-07-02 06:41:17.257 if eqi is None:
2025-07-02 06:41:17.258 eqi, eqj = i, j
2025-07-02 06:41:17.258 continue
2025-07-02 06:41:17.258 cruncher.set_seq1(ai)
2025-07-02 06:41:17.258 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.258 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.258 # compares by a factor of 3.
2025-07-02 06:41:17.258 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.258 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.258 # of the computation is cached by cruncher
2025-07-02 06:41:17.258 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.258 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.258 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.258 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.258 if best_ratio < cutoff:
2025-07-02 06:41:17.258 # no non-identical "pretty close" pair
2025-07-02 06:41:17.258 if eqi is None:
2025-07-02 06:41:17.258 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.258 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.258 return
2025-07-02 06:41:17.258 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.259 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.259 else:
2025-07-02 06:41:17.259 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.259 eqi = None
2025-07-02 06:41:17.259
2025-07-02 06:41:17.259 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.259 # identical
2025-07-02 06:41:17.259
2025-07-02 06:41:17.259 # pump out diffs from before the synch point
2025-07-02 06:41:17.259 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.259
2025-07-02 06:41:17.259 # do intraline marking on the synch pair
2025-07-02 06:41:17.259 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.259 if eqi is None:
2025-07-02 06:41:17.259 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.259 atags = btags = ""
2025-07-02 06:41:17.259 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.259 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.259 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.259 if tag == 'replace':
2025-07-02 06:41:17.260 atags += '^' * la
2025-07-02 06:41:17.260 btags += '^' * lb
2025-07-02 06:41:17.260 elif tag == 'delete':
2025-07-02 06:41:17.260 atags += '-' * la
2025-07-02 06:41:17.260 elif tag == 'insert':
2025-07-02 06:41:17.260 btags += '+' * lb
2025-07-02 06:41:17.260 elif tag == 'equal':
2025-07-02 06:41:17.260 atags += ' ' * la
2025-07-02 06:41:17.260 btags += ' ' * lb
2025-07-02 06:41:17.260 else:
2025-07-02 06:41:17.260 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.260 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.260 else:
2025-07-02 06:41:17.260 # the synch pair is identical
2025-07-02 06:41:17.260 yield ' ' + aelt
2025-07-02 06:41:17.260
2025-07-02 06:41:17.260 # pump out diffs from after the synch point
2025-07-02 06:41:17.260 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.260
2025-07-02 06:41:17.260 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.260 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.261 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.261 alo = 198, ahi = 1101
2025-07-02 06:41:17.261 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.261 blo = 198, bhi = 1101
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.261 g = []
2025-07-02 06:41:17.261 if alo < ahi:
2025-07-02 06:41:17.261 if blo < bhi:
2025-07-02 06:41:17.261 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.261 else:
2025-07-02 06:41:17.261 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.261 elif blo < bhi:
2025-07-02 06:41:17.261 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 > yield from g
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.262 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.262 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.262 alo = 198, ahi = 1101
2025-07-02 06:41:17.262 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.262 blo = 198, bhi = 1101
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.262 r"""
2025-07-02 06:41:17.262 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.262 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.262 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.262 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262 Example:
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262 >>> d = Differ()
2025-07-02 06:41:17.262 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.262 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.263 >>> print(''.join(results), end="")
2025-07-02 06:41:17.263 - abcDefghiJkl
2025-07-02 06:41:17.263 + abcdefGhijkl
2025-07-02 06:41:17.263 """
2025-07-02 06:41:17.263
2025-07-02 06:41:17.263 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.263 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.263 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.263 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.263 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.263
2025-07-02 06:41:17.263 # search for the pair that matches best without being identical
2025-07-02 06:41:17.263 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.263 # on junk -- unless we have to)
2025-07-02 06:41:17.263 for j in range(blo, bhi):
2025-07-02 06:41:17.263 bj = b[j]
2025-07-02 06:41:17.263 cruncher.set_seq2(bj)
2025-07-02 06:41:17.263 for i in range(alo, ahi):
2025-07-02 06:41:17.264 ai = a[i]
2025-07-02 06:41:17.264 if ai == bj:
2025-07-02 06:41:17.264 if eqi is None:
2025-07-02 06:41:17.264 eqi, eqj = i, j
2025-07-02 06:41:17.264 continue
2025-07-02 06:41:17.264 cruncher.set_seq1(ai)
2025-07-02 06:41:17.264 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.264 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.264 # compares by a factor of 3.
2025-07-02 06:41:17.264 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.264 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.264 # of the computation is cached by cruncher
2025-07-02 06:41:17.264 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.264 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.264 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.264 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.264 if best_ratio < cutoff:
2025-07-02 06:41:17.264 # no non-identical "pretty close" pair
2025-07-02 06:41:17.264 if eqi is None:
2025-07-02 06:41:17.264 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.265 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.265 return
2025-07-02 06:41:17.265 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.265 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.265 else:
2025-07-02 06:41:17.265 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.265 eqi = None
2025-07-02 06:41:17.265
2025-07-02 06:41:17.265 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.265 # identical
2025-07-02 06:41:17.265
2025-07-02 06:41:17.265 # pump out diffs from before the synch point
2025-07-02 06:41:17.265 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.265
2025-07-02 06:41:17.265 # do intraline marking on the synch pair
2025-07-02 06:41:17.265 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.265 if eqi is None:
2025-07-02 06:41:17.265 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.266 atags = btags = ""
2025-07-02 06:41:17.266 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.266 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.266 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.266 if tag == 'replace':
2025-07-02 06:41:17.266 atags += '^' * la
2025-07-02 06:41:17.266 btags += '^' * lb
2025-07-02 06:41:17.266 elif tag == 'delete':
2025-07-02 06:41:17.266 atags += '-' * la
2025-07-02 06:41:17.266 elif tag == 'insert':
2025-07-02 06:41:17.266 btags += '+' * lb
2025-07-02 06:41:17.266 elif tag == 'equal':
2025-07-02 06:41:17.266 atags += ' ' * la
2025-07-02 06:41:17.266 btags += ' ' * lb
2025-07-02 06:41:17.266 else:
2025-07-02 06:41:17.266 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.266 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.266 else:
2025-07-02 06:41:17.266 # the synch pair is identical
2025-07-02 06:41:17.267 yield ' ' + aelt
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267 # pump out diffs from after the synch point
2025-07-02 06:41:17.267 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.267 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.267 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.267 alo = 199, ahi = 1101
2025-07-02 06:41:17.267 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.267 blo = 199, bhi = 1101
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.267 g = []
2025-07-02 06:41:17.267 if alo < ahi:
2025-07-02 06:41:17.267 if blo < bhi:
2025-07-02 06:41:17.268 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.268 else:
2025-07-02 06:41:17.268 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.268 elif blo < bhi:
2025-07-02 06:41:17.268 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 > yield from g
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.268 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.268 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.268 alo = 199, ahi = 1101
2025-07-02 06:41:17.268 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.268 blo = 199, bhi = 1101
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.268 r"""
2025-07-02 06:41:17.268 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.269 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.269 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.269 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.269
2025-07-02 06:41:17.269 Example:
2025-07-02 06:41:17.269
2025-07-02 06:41:17.269 >>> d = Differ()
2025-07-02 06:41:17.269 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.269 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.269 >>> print(''.join(results), end="")
2025-07-02 06:41:17.269 - abcDefghiJkl
2025-07-02 06:41:17.269 + abcdefGhijkl
2025-07-02 06:41:17.269 """
2025-07-02 06:41:17.269
2025-07-02 06:41:17.269 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.269 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.269 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.269 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.270 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.270
2025-07-02 06:41:17.270 # search for the pair that matches best without being identical
2025-07-02 06:41:17.270 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.270 # on junk -- unless we have to)
2025-07-02 06:41:17.270 for j in range(blo, bhi):
2025-07-02 06:41:17.270 bj = b[j]
2025-07-02 06:41:17.270 cruncher.set_seq2(bj)
2025-07-02 06:41:17.270 for i in range(alo, ahi):
2025-07-02 06:41:17.270 ai = a[i]
2025-07-02 06:41:17.270 if ai == bj:
2025-07-02 06:41:17.270 if eqi is None:
2025-07-02 06:41:17.270 eqi, eqj = i, j
2025-07-02 06:41:17.270 continue
2025-07-02 06:41:17.270 cruncher.set_seq1(ai)
2025-07-02 06:41:17.270 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.270 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.270 # compares by a factor of 3.
2025-07-02 06:41:17.270 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.270 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.270 # of the computation is cached by cruncher
2025-07-02 06:41:17.271 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.271 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.271 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.271 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.271 if best_ratio < cutoff:
2025-07-02 06:41:17.271 # no non-identical "pretty close" pair
2025-07-02 06:41:17.271 if eqi is None:
2025-07-02 06:41:17.271 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.271 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.271 return
2025-07-02 06:41:17.271 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.271 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.271 else:
2025-07-02 06:41:17.271 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.271 eqi = None
2025-07-02 06:41:17.271
2025-07-02 06:41:17.271 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.271 # identical
2025-07-02 06:41:17.271
2025-07-02 06:41:17.271 # pump out diffs from before the synch point
2025-07-02 06:41:17.272 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.272
2025-07-02 06:41:17.272 # do intraline marking on the synch pair
2025-07-02 06:41:17.272 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.272 if eqi is None:
2025-07-02 06:41:17.272 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.272 atags = btags = ""
2025-07-02 06:41:17.272 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.272 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.272 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.272 if tag == 'replace':
2025-07-02 06:41:17.272 atags += '^' * la
2025-07-02 06:41:17.272 btags += '^' * lb
2025-07-02 06:41:17.272 elif tag == 'delete':
2025-07-02 06:41:17.272 atags += '-' * la
2025-07-02 06:41:17.272 elif tag == 'insert':
2025-07-02 06:41:17.272 btags += '+' * lb
2025-07-02 06:41:17.272 elif tag == 'equal':
2025-07-02 06:41:17.272 atags += ' ' * la
2025-07-02 06:41:17.272 btags += ' ' * lb
2025-07-02 06:41:17.272 else:
2025-07-02 06:41:17.273 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.273 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.273 else:
2025-07-02 06:41:17.273 # the synch pair is identical
2025-07-02 06:41:17.273 yield ' ' + aelt
2025-07-02 06:41:17.273
2025-07-02 06:41:17.273 # pump out diffs from after the synch point
2025-07-02 06:41:17.273 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.273
2025-07-02 06:41:17.273 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.273 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.273
2025-07-02 06:41:17.273 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.273 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.273 alo = 202, ahi = 1101
2025-07-02 06:41:17.273 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.273 blo = 202, bhi = 1101
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.274 g = []
2025-07-02 06:41:17.274 if alo < ahi:
2025-07-02 06:41:17.274 if blo < bhi:
2025-07-02 06:41:17.274 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.274 else:
2025-07-02 06:41:17.274 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.274 elif blo < bhi:
2025-07-02 06:41:17.274 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 > yield from g
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.274 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.274 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.274 alo = 202, ahi = 1101
2025-07-02 06:41:17.274 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.275 blo = 202, bhi = 1101
2025-07-02 06:41:17.275
2025-07-02 06:41:17.275 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.275 r"""
2025-07-02 06:41:17.275 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.275 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.275 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.275 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.275
2025-07-02 06:41:17.275 Example:
2025-07-02 06:41:17.275
2025-07-02 06:41:17.275 >>> d = Differ()
2025-07-02 06:41:17.275 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.275 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.275 >>> print(''.join(results), end="")
2025-07-02 06:41:17.275 - abcDefghiJkl
2025-07-02 06:41:17.276 + abcdefGhijkl
2025-07-02 06:41:17.276 """
2025-07-02 06:41:17.276
2025-07-02 06:41:17.276 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.276 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.276 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.276 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.276 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.276
2025-07-02 06:41:17.276 # search for the pair that matches best without being identical
2025-07-02 06:41:17.276 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.276 # on junk -- unless we have to)
2025-07-02 06:41:17.276 for j in range(blo, bhi):
2025-07-02 06:41:17.276 bj = b[j]
2025-07-02 06:41:17.276 cruncher.set_seq2(bj)
2025-07-02 06:41:17.276 for i in range(alo, ahi):
2025-07-02 06:41:17.276 ai = a[i]
2025-07-02 06:41:17.276 if ai == bj:
2025-07-02 06:41:17.276 if eqi is None:
2025-07-02 06:41:17.276 eqi, eqj = i, j
2025-07-02 06:41:17.277 continue
2025-07-02 06:41:17.277 cruncher.set_seq1(ai)
2025-07-02 06:41:17.277 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.277 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.277 # compares by a factor of 3.
2025-07-02 06:41:17.277 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.277 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.277 # of the computation is cached by cruncher
2025-07-02 06:41:17.277 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.277 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.277 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.277 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.277 if best_ratio < cutoff:
2025-07-02 06:41:17.277 # no non-identical "pretty close" pair
2025-07-02 06:41:17.277 if eqi is None:
2025-07-02 06:41:17.277 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.277 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.277 return
2025-07-02 06:41:17.277 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.277 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.278 else:
2025-07-02 06:41:17.278 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.278 eqi = None
2025-07-02 06:41:17.278
2025-07-02 06:41:17.278 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.278 # identical
2025-07-02 06:41:17.278
2025-07-02 06:41:17.278 # pump out diffs from before the synch point
2025-07-02 06:41:17.278 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.278
2025-07-02 06:41:17.278 # do intraline marking on the synch pair
2025-07-02 06:41:17.278 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.278 if eqi is None:
2025-07-02 06:41:17.278 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.278 atags = btags = ""
2025-07-02 06:41:17.278 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.278 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.278 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.278 if tag == 'replace':
2025-07-02 06:41:17.278 atags += '^' * la
2025-07-02 06:41:17.278 btags += '^' * lb
2025-07-02 06:41:17.279 elif tag == 'delete':
2025-07-02 06:41:17.279 atags += '-' * la
2025-07-02 06:41:17.279 elif tag == 'insert':
2025-07-02 06:41:17.279 btags += '+' * lb
2025-07-02 06:41:17.279 elif tag == 'equal':
2025-07-02 06:41:17.279 atags += ' ' * la
2025-07-02 06:41:17.279 btags += ' ' * lb
2025-07-02 06:41:17.279 else:
2025-07-02 06:41:17.279 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.279 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.279 else:
2025-07-02 06:41:17.279 # the synch pair is identical
2025-07-02 06:41:17.279 yield ' ' + aelt
2025-07-02 06:41:17.279
2025-07-02 06:41:17.279 # pump out diffs from after the synch point
2025-07-02 06:41:17.279 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.279
2025-07-02 06:41:17.279 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.279 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.279
2025-07-02 06:41:17.280 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.280 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.280 alo = 203, ahi = 1101
2025-07-02 06:41:17.280 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.280 blo = 203, bhi = 1101
2025-07-02 06:41:17.280
2025-07-02 06:41:17.280 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.280 g = []
2025-07-02 06:41:17.280 if alo < ahi:
2025-07-02 06:41:17.280 if blo < bhi:
2025-07-02 06:41:17.280 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.280 else:
2025-07-02 06:41:17.280 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.280 elif blo < bhi:
2025-07-02 06:41:17.280 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.280
2025-07-02 06:41:17.280 > yield from g
2025-07-02 06:41:17.280
2025-07-02 06:41:17.280 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.280 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.281 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.281 alo = 203, ahi = 1101
2025-07-02 06:41:17.281 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.281 blo = 203, bhi = 1101
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.281 r"""
2025-07-02 06:41:17.281 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.281 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.281 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.281 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281 Example:
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281 >>> d = Differ()
2025-07-02 06:41:17.281 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.281 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.281 >>> print(''.join(results), end="")
2025-07-02 06:41:17.281 - abcDefghiJkl
2025-07-02 06:41:17.282 + abcdefGhijkl
2025-07-02 06:41:17.282 """
2025-07-02 06:41:17.282
2025-07-02 06:41:17.282 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.282 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.282 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.282 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.282 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.282
2025-07-02 06:41:17.282 # search for the pair that matches best without being identical
2025-07-02 06:41:17.282 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.282 # on junk -- unless we have to)
2025-07-02 06:41:17.282 for j in range(blo, bhi):
2025-07-02 06:41:17.282 bj = b[j]
2025-07-02 06:41:17.282 cruncher.set_seq2(bj)
2025-07-02 06:41:17.282 for i in range(alo, ahi):
2025-07-02 06:41:17.282 ai = a[i]
2025-07-02 06:41:17.283 if ai == bj:
2025-07-02 06:41:17.283 if eqi is None:
2025-07-02 06:41:17.283 eqi, eqj = i, j
2025-07-02 06:41:17.283 continue
2025-07-02 06:41:17.283 cruncher.set_seq1(ai)
2025-07-02 06:41:17.283 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.283 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.283 # compares by a factor of 3.
2025-07-02 06:41:17.283 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.283 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.283 # of the computation is cached by cruncher
2025-07-02 06:41:17.283 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.283 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.283 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.283 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.283 if best_ratio < cutoff:
2025-07-02 06:41:17.283 # no non-identical "pretty close" pair
2025-07-02 06:41:17.283 if eqi is None:
2025-07-02 06:41:17.283 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.284 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.284 return
2025-07-02 06:41:17.284 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.284 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.284 else:
2025-07-02 06:41:17.284 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.284 eqi = None
2025-07-02 06:41:17.284
2025-07-02 06:41:17.284 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.284 # identical
2025-07-02 06:41:17.284
2025-07-02 06:41:17.284 # pump out diffs from before the synch point
2025-07-02 06:41:17.284 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.284
2025-07-02 06:41:17.284 # do intraline marking on the synch pair
2025-07-02 06:41:17.284 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.284 if eqi is None:
2025-07-02 06:41:17.284 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.284 atags = btags = ""
2025-07-02 06:41:17.285 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.285 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.285 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.285 if tag == 'replace':
2025-07-02 06:41:17.285 atags += '^' * la
2025-07-02 06:41:17.285 btags += '^' * lb
2025-07-02 06:41:17.285 elif tag == 'delete':
2025-07-02 06:41:17.285 atags += '-' * la
2025-07-02 06:41:17.285 elif tag == 'insert':
2025-07-02 06:41:17.285 btags += '+' * lb
2025-07-02 06:41:17.285 elif tag == 'equal':
2025-07-02 06:41:17.285 atags += ' ' * la
2025-07-02 06:41:17.285 btags += ' ' * lb
2025-07-02 06:41:17.285 else:
2025-07-02 06:41:17.285 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.285 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.285 else:
2025-07-02 06:41:17.285 # the synch pair is identical
2025-07-02 06:41:17.285 yield ' ' + aelt
2025-07-02 06:41:17.285
2025-07-02 06:41:17.285 # pump out diffs from after the synch point
2025-07-02 06:41:17.286 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.286
2025-07-02 06:41:17.286 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.286 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.286
2025-07-02 06:41:17.286 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.286 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.286 alo = 204, ahi = 1101
2025-07-02 06:41:17.286 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.286 blo = 204, bhi = 1101
2025-07-02 06:41:17.286
2025-07-02 06:41:17.286 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.286 g = []
2025-07-02 06:41:17.286 if alo < ahi:
2025-07-02 06:41:17.286 if blo < bhi:
2025-07-02 06:41:17.286 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.286 else:
2025-07-02 06:41:17.286 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.286 elif blo < bhi:
2025-07-02 06:41:17.286 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 > yield from g
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.287 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.287 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.287 alo = 204, ahi = 1101
2025-07-02 06:41:17.287 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.287 blo = 204, bhi = 1101
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.287 r"""
2025-07-02 06:41:17.287 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.287 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.287 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.287 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 Example:
2025-07-02 06:41:17.288
2025-07-02 06:41:17.288 >>> d = Differ()
2025-07-02 06:41:17.288 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.288 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.288 >>> print(''.join(results), end="")
2025-07-02 06:41:17.288 - abcDefghiJkl
2025-07-02 06:41:17.288 + abcdefGhijkl
2025-07-02 06:41:17.288 """
2025-07-02 06:41:17.288
2025-07-02 06:41:17.288 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.288 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.288 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.288 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.288 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.288
2025-07-02 06:41:17.288 # search for the pair that matches best without being identical
2025-07-02 06:41:17.288 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.288 # on junk -- unless we have to)
2025-07-02 06:41:17.289 for j in range(blo, bhi):
2025-07-02 06:41:17.289 bj = b[j]
2025-07-02 06:41:17.289 cruncher.set_seq2(bj)
2025-07-02 06:41:17.289 for i in range(alo, ahi):
2025-07-02 06:41:17.289 ai = a[i]
2025-07-02 06:41:17.289 if ai == bj:
2025-07-02 06:41:17.289 if eqi is None:
2025-07-02 06:41:17.289 eqi, eqj = i, j
2025-07-02 06:41:17.289 continue
2025-07-02 06:41:17.289 cruncher.set_seq1(ai)
2025-07-02 06:41:17.289 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.289 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.289 # compares by a factor of 3.
2025-07-02 06:41:17.289 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.289 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.289 # of the computation is cached by cruncher
2025-07-02 06:41:17.289 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.289 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.289 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.289 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.290 if best_ratio < cutoff:
2025-07-02 06:41:17.290 # no non-identical "pretty close" pair
2025-07-02 06:41:17.290 if eqi is None:
2025-07-02 06:41:17.290 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.290 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.290 return
2025-07-02 06:41:17.290 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.290 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.290 else:
2025-07-02 06:41:17.290 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.290 eqi = None
2025-07-02 06:41:17.290
2025-07-02 06:41:17.290 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.290 # identical
2025-07-02 06:41:17.290
2025-07-02 06:41:17.290 # pump out diffs from before the synch point
2025-07-02 06:41:17.290 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.290
2025-07-02 06:41:17.290 # do intraline marking on the synch pair
2025-07-02 06:41:17.290 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.291 if eqi is None:
2025-07-02 06:41:17.291 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.291 atags = btags = ""
2025-07-02 06:41:17.291 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.291 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.291 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.291 if tag == 'replace':
2025-07-02 06:41:17.291 atags += '^' * la
2025-07-02 06:41:17.291 btags += '^' * lb
2025-07-02 06:41:17.291 elif tag == 'delete':
2025-07-02 06:41:17.291 atags += '-' * la
2025-07-02 06:41:17.291 elif tag == 'insert':
2025-07-02 06:41:17.291 btags += '+' * lb
2025-07-02 06:41:17.291 elif tag == 'equal':
2025-07-02 06:41:17.291 atags += ' ' * la
2025-07-02 06:41:17.291 btags += ' ' * lb
2025-07-02 06:41:17.291 else:
2025-07-02 06:41:17.291 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.292 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.292 else:
2025-07-02 06:41:17.292 # the synch pair is identical
2025-07-02 06:41:17.292 yield ' ' + aelt
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292 # pump out diffs from after the synch point
2025-07-02 06:41:17.292 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.292 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.292 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.292 alo = 205, ahi = 1101
2025-07-02 06:41:17.292 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.292 blo = 205, bhi = 1101
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.292 g = []
2025-07-02 06:41:17.293 if alo < ahi:
2025-07-02 06:41:17.293 if blo < bhi:
2025-07-02 06:41:17.293 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.293 else:
2025-07-02 06:41:17.293 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.293 elif blo < bhi:
2025-07-02 06:41:17.293 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 > yield from g
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.293 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.293 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.293 alo = 205, ahi = 1101
2025-07-02 06:41:17.293 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.293 blo = 205, bhi = 1101
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.294 r"""
2025-07-02 06:41:17.294 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.294 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.294 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.294 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.294
2025-07-02 06:41:17.294 Example:
2025-07-02 06:41:17.294
2025-07-02 06:41:17.294 >>> d = Differ()
2025-07-02 06:41:17.294 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.294 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.294 >>> print(''.join(results), end="")
2025-07-02 06:41:17.294 - abcDefghiJkl
2025-07-02 06:41:17.294 + abcdefGhijkl
2025-07-02 06:41:17.294 """
2025-07-02 06:41:17.294
2025-07-02 06:41:17.294 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.294 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.295 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.295 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.295 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.295
2025-07-02 06:41:17.295 # search for the pair that matches best without being identical
2025-07-02 06:41:17.295 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.295 # on junk -- unless we have to)
2025-07-02 06:41:17.295 for j in range(blo, bhi):
2025-07-02 06:41:17.295 bj = b[j]
2025-07-02 06:41:17.295 cruncher.set_seq2(bj)
2025-07-02 06:41:17.295 for i in range(alo, ahi):
2025-07-02 06:41:17.295 ai = a[i]
2025-07-02 06:41:17.295 if ai == bj:
2025-07-02 06:41:17.295 if eqi is None:
2025-07-02 06:41:17.295 eqi, eqj = i, j
2025-07-02 06:41:17.295 continue
2025-07-02 06:41:17.295 cruncher.set_seq1(ai)
2025-07-02 06:41:17.295 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.295 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.295 # compares by a factor of 3.
2025-07-02 06:41:17.295 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.296 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.296 # of the computation is cached by cruncher
2025-07-02 06:41:17.296 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.296 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.296 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.296 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.296 if best_ratio < cutoff:
2025-07-02 06:41:17.296 # no non-identical "pretty close" pair
2025-07-02 06:41:17.296 if eqi is None:
2025-07-02 06:41:17.296 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.296 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.296 return
2025-07-02 06:41:17.296 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.296 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.296 else:
2025-07-02 06:41:17.296 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.296 eqi = None
2025-07-02 06:41:17.296
2025-07-02 06:41:17.296 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.296 # identical
2025-07-02 06:41:17.297
2025-07-02 06:41:17.297 # pump out diffs from before the synch point
2025-07-02 06:41:17.297 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.297
2025-07-02 06:41:17.297 # do intraline marking on the synch pair
2025-07-02 06:41:17.297 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.297 if eqi is None:
2025-07-02 06:41:17.297 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.297 atags = btags = ""
2025-07-02 06:41:17.297 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.297 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.297 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.297 if tag == 'replace':
2025-07-02 06:41:17.297 atags += '^' * la
2025-07-02 06:41:17.297 btags += '^' * lb
2025-07-02 06:41:17.297 elif tag == 'delete':
2025-07-02 06:41:17.297 atags += '-' * la
2025-07-02 06:41:17.297 elif tag == 'insert':
2025-07-02 06:41:17.297 btags += '+' * lb
2025-07-02 06:41:17.297 elif tag == 'equal':
2025-07-02 06:41:17.298 atags += ' ' * la
2025-07-02 06:41:17.298 btags += ' ' * lb
2025-07-02 06:41:17.298 else:
2025-07-02 06:41:17.298 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.298 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.298 else:
2025-07-02 06:41:17.298 # the synch pair is identical
2025-07-02 06:41:17.298 yield ' ' + aelt
2025-07-02 06:41:17.298
2025-07-02 06:41:17.298 # pump out diffs from after the synch point
2025-07-02 06:41:17.298 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.298
2025-07-02 06:41:17.298 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.298 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.298
2025-07-02 06:41:17.298 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.298 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.298 alo = 206, ahi = 1101
2025-07-02 06:41:17.298 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.298 blo = 206, bhi = 1101
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.299 g = []
2025-07-02 06:41:17.299 if alo < ahi:
2025-07-02 06:41:17.299 if blo < bhi:
2025-07-02 06:41:17.299 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.299 else:
2025-07-02 06:41:17.299 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.299 elif blo < bhi:
2025-07-02 06:41:17.299 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 > yield from g
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.299 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.299 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.300 alo = 206, ahi = 1101
2025-07-02 06:41:17.300 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.300 blo = 206, bhi = 1101
2025-07-02 06:41:17.300
2025-07-02 06:41:17.300 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.300 r"""
2025-07-02 06:41:17.300 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.300 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.300 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.300 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.300
2025-07-02 06:41:17.300 Example:
2025-07-02 06:41:17.300
2025-07-02 06:41:17.300 >>> d = Differ()
2025-07-02 06:41:17.300 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.300 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.300 >>> print(''.join(results), end="")
2025-07-02 06:41:17.300 - abcDefghiJkl
2025-07-02 06:41:17.301 + abcdefGhijkl
2025-07-02 06:41:17.301 """
2025-07-02 06:41:17.301
2025-07-02 06:41:17.301 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.301 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.301 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.301 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.301 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.301
2025-07-02 06:41:17.301 # search for the pair that matches best without being identical
2025-07-02 06:41:17.301 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.301 # on junk -- unless we have to)
2025-07-02 06:41:17.301 for j in range(blo, bhi):
2025-07-02 06:41:17.301 bj = b[j]
2025-07-02 06:41:17.301 cruncher.set_seq2(bj)
2025-07-02 06:41:17.301 for i in range(alo, ahi):
2025-07-02 06:41:17.301 ai = a[i]
2025-07-02 06:41:17.301 if ai == bj:
2025-07-02 06:41:17.301 if eqi is None:
2025-07-02 06:41:17.302 eqi, eqj = i, j
2025-07-02 06:41:17.302 continue
2025-07-02 06:41:17.302 cruncher.set_seq1(ai)
2025-07-02 06:41:17.302 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.302 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.302 # compares by a factor of 3.
2025-07-02 06:41:17.302 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.302 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.302 # of the computation is cached by cruncher
2025-07-02 06:41:17.302 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.302 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.302 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.302 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.302 if best_ratio < cutoff:
2025-07-02 06:41:17.302 # no non-identical "pretty close" pair
2025-07-02 06:41:17.302 if eqi is None:
2025-07-02 06:41:17.302 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.302 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.302 return
2025-07-02 06:41:17.302 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.303 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.303 else:
2025-07-02 06:41:17.303 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.303 eqi = None
2025-07-02 06:41:17.303
2025-07-02 06:41:17.303 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.303 # identical
2025-07-02 06:41:17.303
2025-07-02 06:41:17.303 # pump out diffs from before the synch point
2025-07-02 06:41:17.303 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.303
2025-07-02 06:41:17.303 # do intraline marking on the synch pair
2025-07-02 06:41:17.303 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.303 if eqi is None:
2025-07-02 06:41:17.303 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.303 atags = btags = ""
2025-07-02 06:41:17.303 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.303 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.303 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.303 if tag == 'replace':
2025-07-02 06:41:17.303 atags += '^' * la
2025-07-02 06:41:17.304 btags += '^' * lb
2025-07-02 06:41:17.304 elif tag == 'delete':
2025-07-02 06:41:17.304 atags += '-' * la
2025-07-02 06:41:17.304 elif tag == 'insert':
2025-07-02 06:41:17.304 btags += '+' * lb
2025-07-02 06:41:17.304 elif tag == 'equal':
2025-07-02 06:41:17.304 atags += ' ' * la
2025-07-02 06:41:17.304 btags += ' ' * lb
2025-07-02 06:41:17.304 else:
2025-07-02 06:41:17.304 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.304 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.304 else:
2025-07-02 06:41:17.304 # the synch pair is identical
2025-07-02 06:41:17.304 yield ' ' + aelt
2025-07-02 06:41:17.304
2025-07-02 06:41:17.304 # pump out diffs from after the synch point
2025-07-02 06:41:17.304 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.304
2025-07-02 06:41:17.304 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.304 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.304
2025-07-02 06:41:17.305 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.305 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.305 alo = 207, ahi = 1101
2025-07-02 06:41:17.305 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.305 blo = 207, bhi = 1101
2025-07-02 06:41:17.305
2025-07-02 06:41:17.305 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.305 g = []
2025-07-02 06:41:17.305 if alo < ahi:
2025-07-02 06:41:17.305 if blo < bhi:
2025-07-02 06:41:17.305 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.305 else:
2025-07-02 06:41:17.305 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.305 elif blo < bhi:
2025-07-02 06:41:17.305 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.305
2025-07-02 06:41:17.305 > yield from g
2025-07-02 06:41:17.305
2025-07-02 06:41:17.305 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.305 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.306 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.306 alo = 207, ahi = 1101
2025-07-02 06:41:17.306 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.306 blo = 207, bhi = 1101
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.306 r"""
2025-07-02 06:41:17.306 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.306 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.306 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.306 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306 Example:
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306 >>> d = Differ()
2025-07-02 06:41:17.306 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.306 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.306 >>> print(''.join(results), end="")
2025-07-02 06:41:17.307 - abcDefghiJkl
2025-07-02 06:41:17.307 + abcdefGhijkl
2025-07-02 06:41:17.307 """
2025-07-02 06:41:17.307
2025-07-02 06:41:17.307 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.307 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.307 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.307 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.307 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.307
2025-07-02 06:41:17.307 # search for the pair that matches best without being identical
2025-07-02 06:41:17.307 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.307 # on junk -- unless we have to)
2025-07-02 06:41:17.307 for j in range(blo, bhi):
2025-07-02 06:41:17.307 bj = b[j]
2025-07-02 06:41:17.307 cruncher.set_seq2(bj)
2025-07-02 06:41:17.307 for i in range(alo, ahi):
2025-07-02 06:41:17.307 ai = a[i]
2025-07-02 06:41:17.307 if ai == bj:
2025-07-02 06:41:17.308 if eqi is None:
2025-07-02 06:41:17.308 eqi, eqj = i, j
2025-07-02 06:41:17.308 continue
2025-07-02 06:41:17.308 cruncher.set_seq1(ai)
2025-07-02 06:41:17.308 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.308 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.308 # compares by a factor of 3.
2025-07-02 06:41:17.308 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.308 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.308 # of the computation is cached by cruncher
2025-07-02 06:41:17.308 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.308 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.308 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.308 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.308 if best_ratio < cutoff:
2025-07-02 06:41:17.308 # no non-identical "pretty close" pair
2025-07-02 06:41:17.308 if eqi is None:
2025-07-02 06:41:17.308 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.308 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.309 return
2025-07-02 06:41:17.309 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.309 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.309 else:
2025-07-02 06:41:17.309 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.309 eqi = None
2025-07-02 06:41:17.309
2025-07-02 06:41:17.309 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.309 # identical
2025-07-02 06:41:17.309
2025-07-02 06:41:17.309 # pump out diffs from before the synch point
2025-07-02 06:41:17.309 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.309
2025-07-02 06:41:17.309 # do intraline marking on the synch pair
2025-07-02 06:41:17.309 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.309 if eqi is None:
2025-07-02 06:41:17.309 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.309 atags = btags = ""
2025-07-02 06:41:17.309 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.309 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.310 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.310 if tag == 'replace':
2025-07-02 06:41:17.310 atags += '^' * la
2025-07-02 06:41:17.310 btags += '^' * lb
2025-07-02 06:41:17.310 elif tag == 'delete':
2025-07-02 06:41:17.310 atags += '-' * la
2025-07-02 06:41:17.310 elif tag == 'insert':
2025-07-02 06:41:17.310 btags += '+' * lb
2025-07-02 06:41:17.310 elif tag == 'equal':
2025-07-02 06:41:17.310 atags += ' ' * la
2025-07-02 06:41:17.310 btags += ' ' * lb
2025-07-02 06:41:17.310 else:
2025-07-02 06:41:17.310 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.310 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.310 else:
2025-07-02 06:41:17.310 # the synch pair is identical
2025-07-02 06:41:17.310 yield ' ' + aelt
2025-07-02 06:41:17.310
2025-07-02 06:41:17.310 # pump out diffs from after the synch point
2025-07-02 06:41:17.310 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.311
2025-07-02 06:41:17.311 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.311 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.311
2025-07-02 06:41:17.311 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.311 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.311 alo = 208, ahi = 1101
2025-07-02 06:41:17.311 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.311 blo = 208, bhi = 1101
2025-07-02 06:41:17.311
2025-07-02 06:41:17.311 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.311 g = []
2025-07-02 06:41:17.311 if alo < ahi:
2025-07-02 06:41:17.311 if blo < bhi:
2025-07-02 06:41:17.311 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.311 else:
2025-07-02 06:41:17.311 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.311 elif blo < bhi:
2025-07-02 06:41:17.311 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.311
2025-07-02 06:41:17.312 > yield from g
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.312 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.312 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.312 alo = 208, ahi = 1101
2025-07-02 06:41:17.312 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.312 blo = 208, bhi = 1101
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.312 r"""
2025-07-02 06:41:17.312 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.312 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.312 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.312 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312 Example:
2025-07-02 06:41:17.312
2025-07-02 06:41:17.313 >>> d = Differ()
2025-07-02 06:41:17.313 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.313 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.313 >>> print(''.join(results), end="")
2025-07-02 06:41:17.313 - abcDefghiJkl
2025-07-02 06:41:17.313 + abcdefGhijkl
2025-07-02 06:41:17.313 """
2025-07-02 06:41:17.313
2025-07-02 06:41:17.313 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.313 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.313 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.313 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.313 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.313
2025-07-02 06:41:17.313 # search for the pair that matches best without being identical
2025-07-02 06:41:17.313 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.313 # on junk -- unless we have to)
2025-07-02 06:41:17.313 for j in range(blo, bhi):
2025-07-02 06:41:17.313 bj = b[j]
2025-07-02 06:41:17.314 cruncher.set_seq2(bj)
2025-07-02 06:41:17.314 for i in range(alo, ahi):
2025-07-02 06:41:17.314 ai = a[i]
2025-07-02 06:41:17.314 if ai == bj:
2025-07-02 06:41:17.314 if eqi is None:
2025-07-02 06:41:17.314 eqi, eqj = i, j
2025-07-02 06:41:17.314 continue
2025-07-02 06:41:17.314 cruncher.set_seq1(ai)
2025-07-02 06:41:17.314 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.314 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.314 # compares by a factor of 3.
2025-07-02 06:41:17.314 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.314 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.314 # of the computation is cached by cruncher
2025-07-02 06:41:17.314 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.314 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.314 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.314 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.314 if best_ratio < cutoff:
2025-07-02 06:41:17.314 # no non-identical "pretty close" pair
2025-07-02 06:41:17.314 if eqi is None:
2025-07-02 06:41:17.315 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.315 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.315 return
2025-07-02 06:41:17.315 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.315 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.315 else:
2025-07-02 06:41:17.315 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.315 eqi = None
2025-07-02 06:41:17.315
2025-07-02 06:41:17.315 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.315 # identical
2025-07-02 06:41:17.315
2025-07-02 06:41:17.315 # pump out diffs from before the synch point
2025-07-02 06:41:17.315 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.315
2025-07-02 06:41:17.315 # do intraline marking on the synch pair
2025-07-02 06:41:17.315 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.315 if eqi is None:
2025-07-02 06:41:17.316 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.316 atags = btags = ""
2025-07-02 06:41:17.316 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.316 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.316 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.316 if tag == 'replace':
2025-07-02 06:41:17.316 atags += '^' * la
2025-07-02 06:41:17.316 btags += '^' * lb
2025-07-02 06:41:17.316 elif tag == 'delete':
2025-07-02 06:41:17.316 atags += '-' * la
2025-07-02 06:41:17.316 elif tag == 'insert':
2025-07-02 06:41:17.316 btags += '+' * lb
2025-07-02 06:41:17.316 elif tag == 'equal':
2025-07-02 06:41:17.316 atags += ' ' * la
2025-07-02 06:41:17.316 btags += ' ' * lb
2025-07-02 06:41:17.316 else:
2025-07-02 06:41:17.316 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.316 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.316 else:
2025-07-02 06:41:17.316 # the synch pair is identical
2025-07-02 06:41:17.317 yield ' ' + aelt
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317 # pump out diffs from after the synch point
2025-07-02 06:41:17.317 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.317 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.317 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.317 alo = 209, ahi = 1101
2025-07-02 06:41:17.317 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.317 blo = 209, bhi = 1101
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.317 g = []
2025-07-02 06:41:17.317 if alo < ahi:
2025-07-02 06:41:17.318 if blo < bhi:
2025-07-02 06:41:17.318 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.318 else:
2025-07-02 06:41:17.318 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.318 elif blo < bhi:
2025-07-02 06:41:17.318 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 > yield from g
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.318 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.318 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.318 alo = 209, ahi = 1101
2025-07-02 06:41:17.318 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.318 blo = 209, bhi = 1101
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.319 r"""
2025-07-02 06:41:17.319 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.319 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.319 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.319 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.319
2025-07-02 06:41:17.319 Example:
2025-07-02 06:41:17.319
2025-07-02 06:41:17.319 >>> d = Differ()
2025-07-02 06:41:17.319 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.319 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.319 >>> print(''.join(results), end="")
2025-07-02 06:41:17.319 - abcDefghiJkl
2025-07-02 06:41:17.319 + abcdefGhijkl
2025-07-02 06:41:17.319 """
2025-07-02 06:41:17.319
2025-07-02 06:41:17.319 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.319 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.320 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.320 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.320 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.320
2025-07-02 06:41:17.320 # search for the pair that matches best without being identical
2025-07-02 06:41:17.320 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.320 # on junk -- unless we have to)
2025-07-02 06:41:17.320 for j in range(blo, bhi):
2025-07-02 06:41:17.320 bj = b[j]
2025-07-02 06:41:17.320 cruncher.set_seq2(bj)
2025-07-02 06:41:17.320 for i in range(alo, ahi):
2025-07-02 06:41:17.320 ai = a[i]
2025-07-02 06:41:17.320 if ai == bj:
2025-07-02 06:41:17.320 if eqi is None:
2025-07-02 06:41:17.320 eqi, eqj = i, j
2025-07-02 06:41:17.320 continue
2025-07-02 06:41:17.320 cruncher.set_seq1(ai)
2025-07-02 06:41:17.320 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.320 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.320 # compares by a factor of 3.
2025-07-02 06:41:17.320 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.321 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.321 # of the computation is cached by cruncher
2025-07-02 06:41:17.321 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.321 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.321 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.321 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.321 if best_ratio < cutoff:
2025-07-02 06:41:17.321 # no non-identical "pretty close" pair
2025-07-02 06:41:17.321 if eqi is None:
2025-07-02 06:41:17.321 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.321 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.321 return
2025-07-02 06:41:17.321 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.321 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.321 else:
2025-07-02 06:41:17.321 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.321 eqi = None
2025-07-02 06:41:17.321
2025-07-02 06:41:17.321 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.322 # identical
2025-07-02 06:41:17.322
2025-07-02 06:41:17.322 # pump out diffs from before the synch point
2025-07-02 06:41:17.322 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.322
2025-07-02 06:41:17.322 # do intraline marking on the synch pair
2025-07-02 06:41:17.322 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.322 if eqi is None:
2025-07-02 06:41:17.322 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.322 atags = btags = ""
2025-07-02 06:41:17.322 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.322 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.322 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.322 if tag == 'replace':
2025-07-02 06:41:17.322 atags += '^' * la
2025-07-02 06:41:17.322 btags += '^' * lb
2025-07-02 06:41:17.322 elif tag == 'delete':
2025-07-02 06:41:17.322 atags += '-' * la
2025-07-02 06:41:17.322 elif tag == 'insert':
2025-07-02 06:41:17.322 btags += '+' * lb
2025-07-02 06:41:17.322 elif tag == 'equal':
2025-07-02 06:41:17.323 atags += ' ' * la
2025-07-02 06:41:17.323 btags += ' ' * lb
2025-07-02 06:41:17.323 else:
2025-07-02 06:41:17.323 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.323 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.323 else:
2025-07-02 06:41:17.323 # the synch pair is identical
2025-07-02 06:41:17.323 yield ' ' + aelt
2025-07-02 06:41:17.323
2025-07-02 06:41:17.323 # pump out diffs from after the synch point
2025-07-02 06:41:17.323 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.323
2025-07-02 06:41:17.323 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.323 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.323
2025-07-02 06:41:17.323 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.323 alo = 210, ahi = 1101
2025-07-02 06:41:17.323 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.323 blo = 210, bhi = 1101
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.324 g = []
2025-07-02 06:41:17.324 if alo < ahi:
2025-07-02 06:41:17.324 if blo < bhi:
2025-07-02 06:41:17.324 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.324 else:
2025-07-02 06:41:17.324 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.324 elif blo < bhi:
2025-07-02 06:41:17.324 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 > yield from g
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.324 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.324 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.324 alo = 210, ahi = 1101
2025-07-02 06:41:17.324 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.325 blo = 210, bhi = 1101
2025-07-02 06:41:17.325
2025-07-02 06:41:17.325 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.325 r"""
2025-07-02 06:41:17.325 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.325 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.325 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.325 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.325
2025-07-02 06:41:17.325 Example:
2025-07-02 06:41:17.325
2025-07-02 06:41:17.325 >>> d = Differ()
2025-07-02 06:41:17.325 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.325 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.325 >>> print(''.join(results), end="")
2025-07-02 06:41:17.325 - abcDefghiJkl
2025-07-02 06:41:17.325 + abcdefGhijkl
2025-07-02 06:41:17.326 """
2025-07-02 06:41:17.326
2025-07-02 06:41:17.326 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.326 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.326 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.326 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.326 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.326
2025-07-02 06:41:17.326 # search for the pair that matches best without being identical
2025-07-02 06:41:17.326 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.326 # on junk -- unless we have to)
2025-07-02 06:41:17.326 for j in range(blo, bhi):
2025-07-02 06:41:17.326 bj = b[j]
2025-07-02 06:41:17.326 cruncher.set_seq2(bj)
2025-07-02 06:41:17.326 for i in range(alo, ahi):
2025-07-02 06:41:17.326 ai = a[i]
2025-07-02 06:41:17.326 if ai == bj:
2025-07-02 06:41:17.326 if eqi is None:
2025-07-02 06:41:17.327 eqi, eqj = i, j
2025-07-02 06:41:17.327 continue
2025-07-02 06:41:17.327 cruncher.set_seq1(ai)
2025-07-02 06:41:17.327 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.327 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.327 # compares by a factor of 3.
2025-07-02 06:41:17.327 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.327 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.327 # of the computation is cached by cruncher
2025-07-02 06:41:17.327 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.327 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.327 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.327 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.327 if best_ratio < cutoff:
2025-07-02 06:41:17.327 # no non-identical "pretty close" pair
2025-07-02 06:41:17.327 if eqi is None:
2025-07-02 06:41:17.327 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.327 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.327 return
2025-07-02 06:41:17.327 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.328 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.328 else:
2025-07-02 06:41:17.328 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.328 eqi = None
2025-07-02 06:41:17.328
2025-07-02 06:41:17.328 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.328 # identical
2025-07-02 06:41:17.328
2025-07-02 06:41:17.328 # pump out diffs from before the synch point
2025-07-02 06:41:17.328 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.328
2025-07-02 06:41:17.328 # do intraline marking on the synch pair
2025-07-02 06:41:17.328 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.328 if eqi is None:
2025-07-02 06:41:17.328 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.328 atags = btags = ""
2025-07-02 06:41:17.328 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.328 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.328 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.328 if tag == 'replace':
2025-07-02 06:41:17.329 atags += '^' * la
2025-07-02 06:41:17.329 btags += '^' * lb
2025-07-02 06:41:17.329 elif tag == 'delete':
2025-07-02 06:41:17.329 atags += '-' * la
2025-07-02 06:41:17.329 elif tag == 'insert':
2025-07-02 06:41:17.329 btags += '+' * lb
2025-07-02 06:41:17.329 elif tag == 'equal':
2025-07-02 06:41:17.329 atags += ' ' * la
2025-07-02 06:41:17.329 btags += ' ' * lb
2025-07-02 06:41:17.329 else:
2025-07-02 06:41:17.329 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.329 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.329 else:
2025-07-02 06:41:17.329 # the synch pair is identical
2025-07-02 06:41:17.329 yield ' ' + aelt
2025-07-02 06:41:17.329
2025-07-02 06:41:17.329 # pump out diffs from after the synch point
2025-07-02 06:41:17.329 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.329
2025-07-02 06:41:17.329 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.329 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.330 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.330 alo = 211, ahi = 1101
2025-07-02 06:41:17.330 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.330 blo = 211, bhi = 1101
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.330 g = []
2025-07-02 06:41:17.330 if alo < ahi:
2025-07-02 06:41:17.330 if blo < bhi:
2025-07-02 06:41:17.330 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.330 else:
2025-07-02 06:41:17.330 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.330 elif blo < bhi:
2025-07-02 06:41:17.330 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 > yield from g
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.331 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.331 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.331 alo = 211, ahi = 1101
2025-07-02 06:41:17.331 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.331 blo = 211, bhi = 1101
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.331 r"""
2025-07-02 06:41:17.331 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.331 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.331 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.331 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331 Example:
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331 >>> d = Differ()
2025-07-02 06:41:17.332 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.332 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.332 >>> print(''.join(results), end="")
2025-07-02 06:41:17.332 - abcDefghiJkl
2025-07-02 06:41:17.332 + abcdefGhijkl
2025-07-02 06:41:17.332 """
2025-07-02 06:41:17.332
2025-07-02 06:41:17.332 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.332 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.332 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.332 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.332 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.332
2025-07-02 06:41:17.332 # search for the pair that matches best without being identical
2025-07-02 06:41:17.332 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.332 # on junk -- unless we have to)
2025-07-02 06:41:17.332 for j in range(blo, bhi):
2025-07-02 06:41:17.332 bj = b[j]
2025-07-02 06:41:17.333 cruncher.set_seq2(bj)
2025-07-02 06:41:17.333 for i in range(alo, ahi):
2025-07-02 06:41:17.333 ai = a[i]
2025-07-02 06:41:17.333 if ai == bj:
2025-07-02 06:41:17.333 if eqi is None:
2025-07-02 06:41:17.333 eqi, eqj = i, j
2025-07-02 06:41:17.333 continue
2025-07-02 06:41:17.333 cruncher.set_seq1(ai)
2025-07-02 06:41:17.333 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.333 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.333 # compares by a factor of 3.
2025-07-02 06:41:17.333 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.333 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.333 # of the computation is cached by cruncher
2025-07-02 06:41:17.333 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.333 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.333 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.333 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.333 if best_ratio < cutoff:
2025-07-02 06:41:17.333 # no non-identical "pretty close" pair
2025-07-02 06:41:17.333 if eqi is None:
2025-07-02 06:41:17.334 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.334 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.334 return
2025-07-02 06:41:17.334 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.334 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.334 else:
2025-07-02 06:41:17.334 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.334 eqi = None
2025-07-02 06:41:17.334
2025-07-02 06:41:17.334 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.334 # identical
2025-07-02 06:41:17.334
2025-07-02 06:41:17.334 # pump out diffs from before the synch point
2025-07-02 06:41:17.334 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.334
2025-07-02 06:41:17.334 # do intraline marking on the synch pair
2025-07-02 06:41:17.334 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.334 if eqi is None:
2025-07-02 06:41:17.335 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.335 atags = btags = ""
2025-07-02 06:41:17.335 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.335 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.335 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.335 if tag == 'replace':
2025-07-02 06:41:17.335 atags += '^' * la
2025-07-02 06:41:17.335 btags += '^' * lb
2025-07-02 06:41:17.335 elif tag == 'delete':
2025-07-02 06:41:17.335 atags += '-' * la
2025-07-02 06:41:17.335 elif tag == 'insert':
2025-07-02 06:41:17.335 btags += '+' * lb
2025-07-02 06:41:17.335 elif tag == 'equal':
2025-07-02 06:41:17.335 atags += ' ' * la
2025-07-02 06:41:17.335 btags += ' ' * lb
2025-07-02 06:41:17.335 else:
2025-07-02 06:41:17.335 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.335 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.335 else:
2025-07-02 06:41:17.336 # the synch pair is identical
2025-07-02 06:41:17.336 yield ' ' + aelt
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336 # pump out diffs from after the synch point
2025-07-02 06:41:17.336 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.336 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.336 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.336 alo = 212, ahi = 1101
2025-07-02 06:41:17.336 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.336 blo = 212, bhi = 1101
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.336 g = []
2025-07-02 06:41:17.336 if alo < ahi:
2025-07-02 06:41:17.336 if blo < bhi:
2025-07-02 06:41:17.337 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.337 else:
2025-07-02 06:41:17.337 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.337 elif blo < bhi:
2025-07-02 06:41:17.337 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 > yield from g
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.337 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.337 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.337 alo = 212, ahi = 1101
2025-07-02 06:41:17.337 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.337 blo = 212, bhi = 1101
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.337 r"""
2025-07-02 06:41:17.337 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.338 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.338 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.338 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.338
2025-07-02 06:41:17.338 Example:
2025-07-02 06:41:17.338
2025-07-02 06:41:17.338 >>> d = Differ()
2025-07-02 06:41:17.338 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.338 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.338 >>> print(''.join(results), end="")
2025-07-02 06:41:17.338 - abcDefghiJkl
2025-07-02 06:41:17.338 + abcdefGhijkl
2025-07-02 06:41:17.338 """
2025-07-02 06:41:17.338
2025-07-02 06:41:17.338 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.338 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.338 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.338 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.338 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.339
2025-07-02 06:41:17.339 # search for the pair that matches best without being identical
2025-07-02 06:41:17.339 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.339 # on junk -- unless we have to)
2025-07-02 06:41:17.339 for j in range(blo, bhi):
2025-07-02 06:41:17.339 bj = b[j]
2025-07-02 06:41:17.339 cruncher.set_seq2(bj)
2025-07-02 06:41:17.339 for i in range(alo, ahi):
2025-07-02 06:41:17.339 ai = a[i]
2025-07-02 06:41:17.339 if ai == bj:
2025-07-02 06:41:17.339 if eqi is None:
2025-07-02 06:41:17.339 eqi, eqj = i, j
2025-07-02 06:41:17.339 continue
2025-07-02 06:41:17.339 cruncher.set_seq1(ai)
2025-07-02 06:41:17.339 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.339 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.339 # compares by a factor of 3.
2025-07-02 06:41:17.339 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.339 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.339 # of the computation is cached by cruncher
2025-07-02 06:41:17.340 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.340 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.340 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.340 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.340 if best_ratio < cutoff:
2025-07-02 06:41:17.340 # no non-identical "pretty close" pair
2025-07-02 06:41:17.340 if eqi is None:
2025-07-02 06:41:17.340 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.340 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.340 return
2025-07-02 06:41:17.340 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.340 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.340 else:
2025-07-02 06:41:17.340 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.340 eqi = None
2025-07-02 06:41:17.340
2025-07-02 06:41:17.340 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.340 # identical
2025-07-02 06:41:17.340
2025-07-02 06:41:17.340 # pump out diffs from before the synch point
2025-07-02 06:41:17.340 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.341
2025-07-02 06:41:17.341 # do intraline marking on the synch pair
2025-07-02 06:41:17.341 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.341 if eqi is None:
2025-07-02 06:41:17.341 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.341 atags = btags = ""
2025-07-02 06:41:17.341 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.341 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.341 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.341 if tag == 'replace':
2025-07-02 06:41:17.341 atags += '^' * la
2025-07-02 06:41:17.341 btags += '^' * lb
2025-07-02 06:41:17.341 elif tag == 'delete':
2025-07-02 06:41:17.341 atags += '-' * la
2025-07-02 06:41:17.341 elif tag == 'insert':
2025-07-02 06:41:17.341 btags += '+' * lb
2025-07-02 06:41:17.341 elif tag == 'equal':
2025-07-02 06:41:17.341 atags += ' ' * la
2025-07-02 06:41:17.341 btags += ' ' * lb
2025-07-02 06:41:17.341 else:
2025-07-02 06:41:17.342 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.342 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.342 else:
2025-07-02 06:41:17.342 # the synch pair is identical
2025-07-02 06:41:17.342 yield ' ' + aelt
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342 # pump out diffs from after the synch point
2025-07-02 06:41:17.342 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.342 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.342 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.342 alo = 213, ahi = 1101
2025-07-02 06:41:17.342 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.342 blo = 213, bhi = 1101
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.342 g = []
2025-07-02 06:41:17.343 if alo < ahi:
2025-07-02 06:41:17.343 if blo < bhi:
2025-07-02 06:41:17.343 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.343 else:
2025-07-02 06:41:17.343 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.343 elif blo < bhi:
2025-07-02 06:41:17.343 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.343
2025-07-02 06:41:17.343 > yield from g
2025-07-02 06:41:17.343
2025-07-02 06:41:17.343 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.343 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.343
2025-07-02 06:41:17.343 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.343 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.343 alo = 213, ahi = 1101
2025-07-02 06:41:17.343 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.343 blo = 213, bhi = 1101
2025-07-02 06:41:17.344
2025-07-02 06:41:17.344 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.344 r"""
2025-07-02 06:41:17.344 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.344 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.344 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.344 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.344
2025-07-02 06:41:17.344 Example:
2025-07-02 06:41:17.344
2025-07-02 06:41:17.344 >>> d = Differ()
2025-07-02 06:41:17.344 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.344 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.344 >>> print(''.join(results), end="")
2025-07-02 06:41:17.344 - abcDefghiJkl
2025-07-02 06:41:17.344 + abcdefGhijkl
2025-07-02 06:41:17.344 """
2025-07-02 06:41:17.345
2025-07-02 06:41:17.345 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.345 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.345 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.345 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.345 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.345
2025-07-02 06:41:17.345 # search for the pair that matches best without being identical
2025-07-02 06:41:17.345 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.345 # on junk -- unless we have to)
2025-07-02 06:41:17.345 for j in range(blo, bhi):
2025-07-02 06:41:17.345 bj = b[j]
2025-07-02 06:41:17.345 cruncher.set_seq2(bj)
2025-07-02 06:41:17.345 for i in range(alo, ahi):
2025-07-02 06:41:17.345 ai = a[i]
2025-07-02 06:41:17.345 if ai == bj:
2025-07-02 06:41:17.345 if eqi is None:
2025-07-02 06:41:17.345 eqi, eqj = i, j
2025-07-02 06:41:17.345 continue
2025-07-02 06:41:17.345 cruncher.set_seq1(ai)
2025-07-02 06:41:17.345 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.346 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.346 # compares by a factor of 3.
2025-07-02 06:41:17.346 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.346 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.346 # of the computation is cached by cruncher
2025-07-02 06:41:17.346 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.346 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.346 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.346 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.346 if best_ratio < cutoff:
2025-07-02 06:41:17.346 # no non-identical "pretty close" pair
2025-07-02 06:41:17.346 if eqi is None:
2025-07-02 06:41:17.346 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.346 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.346 return
2025-07-02 06:41:17.346 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.346 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.346 else:
2025-07-02 06:41:17.346 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.346 eqi = None
2025-07-02 06:41:17.347
2025-07-02 06:41:17.347 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.347 # identical
2025-07-02 06:41:17.347
2025-07-02 06:41:17.347 # pump out diffs from before the synch point
2025-07-02 06:41:17.347 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.347
2025-07-02 06:41:17.347 # do intraline marking on the synch pair
2025-07-02 06:41:17.347 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.347 if eqi is None:
2025-07-02 06:41:17.347 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.347 atags = btags = ""
2025-07-02 06:41:17.347 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.347 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.347 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.347 if tag == 'replace':
2025-07-02 06:41:17.347 atags += '^' * la
2025-07-02 06:41:17.347 btags += '^' * lb
2025-07-02 06:41:17.347 elif tag == 'delete':
2025-07-02 06:41:17.348 atags += '-' * la
2025-07-02 06:41:17.348 elif tag == 'insert':
2025-07-02 06:41:17.348 btags += '+' * lb
2025-07-02 06:41:17.348 elif tag == 'equal':
2025-07-02 06:41:17.348 atags += ' ' * la
2025-07-02 06:41:17.348 btags += ' ' * lb
2025-07-02 06:41:17.348 else:
2025-07-02 06:41:17.348 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.348 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.348 else:
2025-07-02 06:41:17.348 # the synch pair is identical
2025-07-02 06:41:17.348 yield ' ' + aelt
2025-07-02 06:41:17.348
2025-07-02 06:41:17.348 # pump out diffs from after the synch point
2025-07-02 06:41:17.348 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.348
2025-07-02 06:41:17.348 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.348 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.348
2025-07-02 06:41:17.349 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.349 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.349 alo = 214, ahi = 1101
2025-07-02 06:41:17.349 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.349 blo = 214, bhi = 1101
2025-07-02 06:41:17.349
2025-07-02 06:41:17.349 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.349 g = []
2025-07-02 06:41:17.349 if alo < ahi:
2025-07-02 06:41:17.349 if blo < bhi:
2025-07-02 06:41:17.349 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.349 else:
2025-07-02 06:41:17.349 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.349 elif blo < bhi:
2025-07-02 06:41:17.349 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.349
2025-07-02 06:41:17.349 > yield from g
2025-07-02 06:41:17.349
2025-07-02 06:41:17.349 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.349 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.350 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.350 alo = 214, ahi = 1101
2025-07-02 06:41:17.350 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.350 blo = 214, bhi = 1101
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.350 r"""
2025-07-02 06:41:17.350 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.350 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.350 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.350 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350 Example:
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350 >>> d = Differ()
2025-07-02 06:41:17.350 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.350 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.350 >>> print(''.join(results), end="")
2025-07-02 06:41:17.351 - abcDefghiJkl
2025-07-02 06:41:17.351 + abcdefGhijkl
2025-07-02 06:41:17.351 """
2025-07-02 06:41:17.351
2025-07-02 06:41:17.351 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.351 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.351 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.351 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.351 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.351
2025-07-02 06:41:17.351 # search for the pair that matches best without being identical
2025-07-02 06:41:17.351 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.351 # on junk -- unless we have to)
2025-07-02 06:41:17.351 for j in range(blo, bhi):
2025-07-02 06:41:17.351 bj = b[j]
2025-07-02 06:41:17.351 cruncher.set_seq2(bj)
2025-07-02 06:41:17.351 for i in range(alo, ahi):
2025-07-02 06:41:17.351 ai = a[i]
2025-07-02 06:41:17.352 if ai == bj:
2025-07-02 06:41:17.352 if eqi is None:
2025-07-02 06:41:17.352 eqi, eqj = i, j
2025-07-02 06:41:17.352 continue
2025-07-02 06:41:17.352 cruncher.set_seq1(ai)
2025-07-02 06:41:17.352 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.352 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.352 # compares by a factor of 3.
2025-07-02 06:41:17.352 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.352 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.352 # of the computation is cached by cruncher
2025-07-02 06:41:17.352 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.352 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.352 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.352 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.352 if best_ratio < cutoff:
2025-07-02 06:41:17.352 # no non-identical "pretty close" pair
2025-07-02 06:41:17.352 if eqi is None:
2025-07-02 06:41:17.353 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.353 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.353 return
2025-07-02 06:41:17.353 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.353 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.353 else:
2025-07-02 06:41:17.353 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.353 eqi = None
2025-07-02 06:41:17.353
2025-07-02 06:41:17.353 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.353 # identical
2025-07-02 06:41:17.353
2025-07-02 06:41:17.353 # pump out diffs from before the synch point
2025-07-02 06:41:17.353 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.353
2025-07-02 06:41:17.353 # do intraline marking on the synch pair
2025-07-02 06:41:17.353 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.353 if eqi is None:
2025-07-02 06:41:17.353 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.354 atags = btags = ""
2025-07-02 06:41:17.354 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.354 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.354 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.354 if tag == 'replace':
2025-07-02 06:41:17.354 atags += '^' * la
2025-07-02 06:41:17.354 btags += '^' * lb
2025-07-02 06:41:17.354 elif tag == 'delete':
2025-07-02 06:41:17.354 atags += '-' * la
2025-07-02 06:41:17.354 elif tag == 'insert':
2025-07-02 06:41:17.354 btags += '+' * lb
2025-07-02 06:41:17.354 elif tag == 'equal':
2025-07-02 06:41:17.354 atags += ' ' * la
2025-07-02 06:41:17.354 btags += ' ' * lb
2025-07-02 06:41:17.354 else:
2025-07-02 06:41:17.354 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.354 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.355 else:
2025-07-02 06:41:17.355 # the synch pair is identical
2025-07-02 06:41:17.355 yield ' ' + aelt
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355 # pump out diffs from after the synch point
2025-07-02 06:41:17.355 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.355 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.355 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.355 alo = 215, ahi = 1101
2025-07-02 06:41:17.355 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.355 blo = 215, bhi = 1101
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.355 g = []
2025-07-02 06:41:17.355 if alo < ahi:
2025-07-02 06:41:17.355 if blo < bhi:
2025-07-02 06:41:17.356 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.356 else:
2025-07-02 06:41:17.356 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.356 elif blo < bhi:
2025-07-02 06:41:17.356 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 > yield from g
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.356 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.356 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.356 alo = 215, ahi = 1101
2025-07-02 06:41:17.356 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.356 blo = 215, bhi = 1101
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.356 r"""
2025-07-02 06:41:17.356 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.357 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.357 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.357 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.357
2025-07-02 06:41:17.357 Example:
2025-07-02 06:41:17.357
2025-07-02 06:41:17.357 >>> d = Differ()
2025-07-02 06:41:17.357 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.357 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.357 >>> print(''.join(results), end="")
2025-07-02 06:41:17.357 - abcDefghiJkl
2025-07-02 06:41:17.357 + abcdefGhijkl
2025-07-02 06:41:17.357 """
2025-07-02 06:41:17.357
2025-07-02 06:41:17.357 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.357 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.357 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.357 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.358 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.358
2025-07-02 06:41:17.358 # search for the pair that matches best without being identical
2025-07-02 06:41:17.358 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.358 # on junk -- unless we have to)
2025-07-02 06:41:17.358 for j in range(blo, bhi):
2025-07-02 06:41:17.358 bj = b[j]
2025-07-02 06:41:17.358 cruncher.set_seq2(bj)
2025-07-02 06:41:17.358 for i in range(alo, ahi):
2025-07-02 06:41:17.358 ai = a[i]
2025-07-02 06:41:17.358 if ai == bj:
2025-07-02 06:41:17.358 if eqi is None:
2025-07-02 06:41:17.358 eqi, eqj = i, j
2025-07-02 06:41:17.358 continue
2025-07-02 06:41:17.358 cruncher.set_seq1(ai)
2025-07-02 06:41:17.358 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.358 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.358 # compares by a factor of 3.
2025-07-02 06:41:17.358 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.358 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.358 # of the computation is cached by cruncher
2025-07-02 06:41:17.359 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.359 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.359 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.359 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.359 if best_ratio < cutoff:
2025-07-02 06:41:17.359 # no non-identical "pretty close" pair
2025-07-02 06:41:17.359 if eqi is None:
2025-07-02 06:41:17.359 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.359 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.359 return
2025-07-02 06:41:17.359 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.359 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.359 else:
2025-07-02 06:41:17.359 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.359 eqi = None
2025-07-02 06:41:17.359
2025-07-02 06:41:17.359 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.359 # identical
2025-07-02 06:41:17.359
2025-07-02 06:41:17.359 # pump out diffs from before the synch point
2025-07-02 06:41:17.360 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.360
2025-07-02 06:41:17.360 # do intraline marking on the synch pair
2025-07-02 06:41:17.360 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.360 if eqi is None:
2025-07-02 06:41:17.360 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.360 atags = btags = ""
2025-07-02 06:41:17.360 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.360 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.360 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.360 if tag == 'replace':
2025-07-02 06:41:17.360 atags += '^' * la
2025-07-02 06:41:17.360 btags += '^' * lb
2025-07-02 06:41:17.360 elif tag == 'delete':
2025-07-02 06:41:17.360 atags += '-' * la
2025-07-02 06:41:17.360 elif tag == 'insert':
2025-07-02 06:41:17.360 btags += '+' * lb
2025-07-02 06:41:17.360 elif tag == 'equal':
2025-07-02 06:41:17.360 atags += ' ' * la
2025-07-02 06:41:17.361 btags += ' ' * lb
2025-07-02 06:41:17.361 else:
2025-07-02 06:41:17.361 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.361 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.361 else:
2025-07-02 06:41:17.361 # the synch pair is identical
2025-07-02 06:41:17.361 yield ' ' + aelt
2025-07-02 06:41:17.361
2025-07-02 06:41:17.361 # pump out diffs from after the synch point
2025-07-02 06:41:17.361 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.361
2025-07-02 06:41:17.361 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.361 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.361
2025-07-02 06:41:17.361 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.361 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.361 alo = 216, ahi = 1101
2025-07-02 06:41:17.361 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.361 blo = 216, bhi = 1101
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.362 g = []
2025-07-02 06:41:17.362 if alo < ahi:
2025-07-02 06:41:17.362 if blo < bhi:
2025-07-02 06:41:17.362 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.362 else:
2025-07-02 06:41:17.362 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.362 elif blo < bhi:
2025-07-02 06:41:17.362 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 > yield from g
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.362 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.362 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.362 alo = 216, ahi = 1101
2025-07-02 06:41:17.362 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.363 blo = 216, bhi = 1101
2025-07-02 06:41:17.363
2025-07-02 06:41:17.363 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.363 r"""
2025-07-02 06:41:17.363 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.363 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.363 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.363 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.363
2025-07-02 06:41:17.363 Example:
2025-07-02 06:41:17.363
2025-07-02 06:41:17.363 >>> d = Differ()
2025-07-02 06:41:17.363 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.363 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.363 >>> print(''.join(results), end="")
2025-07-02 06:41:17.363 - abcDefghiJkl
2025-07-02 06:41:17.364 + abcdefGhijkl
2025-07-02 06:41:17.364 """
2025-07-02 06:41:17.364
2025-07-02 06:41:17.364 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.364 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.364 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.364 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.364 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.364
2025-07-02 06:41:17.364 # search for the pair that matches best without being identical
2025-07-02 06:41:17.364 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.364 # on junk -- unless we have to)
2025-07-02 06:41:17.364 for j in range(blo, bhi):
2025-07-02 06:41:17.364 bj = b[j]
2025-07-02 06:41:17.364 cruncher.set_seq2(bj)
2025-07-02 06:41:17.364 for i in range(alo, ahi):
2025-07-02 06:41:17.364 ai = a[i]
2025-07-02 06:41:17.364 if ai == bj:
2025-07-02 06:41:17.364 if eqi is None:
2025-07-02 06:41:17.365 eqi, eqj = i, j
2025-07-02 06:41:17.365 continue
2025-07-02 06:41:17.365 cruncher.set_seq1(ai)
2025-07-02 06:41:17.365 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.365 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.365 # compares by a factor of 3.
2025-07-02 06:41:17.365 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.365 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.365 # of the computation is cached by cruncher
2025-07-02 06:41:17.365 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.365 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.365 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.365 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.365 if best_ratio < cutoff:
2025-07-02 06:41:17.365 # no non-identical "pretty close" pair
2025-07-02 06:41:17.365 if eqi is None:
2025-07-02 06:41:17.365 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.365 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.365 return
2025-07-02 06:41:17.366 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.366 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.366 else:
2025-07-02 06:41:17.366 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.366 eqi = None
2025-07-02 06:41:17.366
2025-07-02 06:41:17.366 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.366 # identical
2025-07-02 06:41:17.366
2025-07-02 06:41:17.366 # pump out diffs from before the synch point
2025-07-02 06:41:17.366 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.366
2025-07-02 06:41:17.366 # do intraline marking on the synch pair
2025-07-02 06:41:17.366 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.366 if eqi is None:
2025-07-02 06:41:17.366 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.366 atags = btags = ""
2025-07-02 06:41:17.366 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.366 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.366 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.367 if tag == 'replace':
2025-07-02 06:41:17.367 atags += '^' * la
2025-07-02 06:41:17.367 btags += '^' * lb
2025-07-02 06:41:17.367 elif tag == 'delete':
2025-07-02 06:41:17.367 atags += '-' * la
2025-07-02 06:41:17.367 elif tag == 'insert':
2025-07-02 06:41:17.367 btags += '+' * lb
2025-07-02 06:41:17.367 elif tag == 'equal':
2025-07-02 06:41:17.367 atags += ' ' * la
2025-07-02 06:41:17.367 btags += ' ' * lb
2025-07-02 06:41:17.367 else:
2025-07-02 06:41:17.367 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.367 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.367 else:
2025-07-02 06:41:17.367 # the synch pair is identical
2025-07-02 06:41:17.367 yield ' ' + aelt
2025-07-02 06:41:17.367
2025-07-02 06:41:17.367 # pump out diffs from after the synch point
2025-07-02 06:41:17.367 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.367
2025-07-02 06:41:17.368 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.368 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.368
2025-07-02 06:41:17.368 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.368 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.368 alo = 217, ahi = 1101
2025-07-02 06:41:17.368 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.368 blo = 217, bhi = 1101
2025-07-02 06:41:17.368
2025-07-02 06:41:17.368 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.368 g = []
2025-07-02 06:41:17.368 if alo < ahi:
2025-07-02 06:41:17.368 if blo < bhi:
2025-07-02 06:41:17.368 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.368 else:
2025-07-02 06:41:17.368 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.368 elif blo < bhi:
2025-07-02 06:41:17.368 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.368
2025-07-02 06:41:17.369 > yield from g
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.369 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.369 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.369 alo = 217, ahi = 1101
2025-07-02 06:41:17.369 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.369 blo = 217, bhi = 1101
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.369 r"""
2025-07-02 06:41:17.369 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.369 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.369 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.369 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369 Example:
2025-07-02 06:41:17.370
2025-07-02 06:41:17.370 >>> d = Differ()
2025-07-02 06:41:17.370 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.370 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.370 >>> print(''.join(results), end="")
2025-07-02 06:41:17.370 - abcDefghiJkl
2025-07-02 06:41:17.370 + abcdefGhijkl
2025-07-02 06:41:17.370 """
2025-07-02 06:41:17.370
2025-07-02 06:41:17.370 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.370 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.370 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.370 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.370 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.370
2025-07-02 06:41:17.370 # search for the pair that matches best without being identical
2025-07-02 06:41:17.370 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.370 # on junk -- unless we have to)
2025-07-02 06:41:17.371 for j in range(blo, bhi):
2025-07-02 06:41:17.371 bj = b[j]
2025-07-02 06:41:17.371 cruncher.set_seq2(bj)
2025-07-02 06:41:17.371 for i in range(alo, ahi):
2025-07-02 06:41:17.371 ai = a[i]
2025-07-02 06:41:17.371 if ai == bj:
2025-07-02 06:41:17.371 if eqi is None:
2025-07-02 06:41:17.371 eqi, eqj = i, j
2025-07-02 06:41:17.371 continue
2025-07-02 06:41:17.371 cruncher.set_seq1(ai)
2025-07-02 06:41:17.371 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.371 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.371 # compares by a factor of 3.
2025-07-02 06:41:17.371 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.371 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.371 # of the computation is cached by cruncher
2025-07-02 06:41:17.371 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.371 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.371 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.372 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.372 if best_ratio < cutoff:
2025-07-02 06:41:17.372 # no non-identical "pretty close" pair
2025-07-02 06:41:17.372 if eqi is None:
2025-07-02 06:41:17.372 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.372 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.372 return
2025-07-02 06:41:17.372 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.372 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.372 else:
2025-07-02 06:41:17.372 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.372 eqi = None
2025-07-02 06:41:17.372
2025-07-02 06:41:17.372 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.372 # identical
2025-07-02 06:41:17.372
2025-07-02 06:41:17.372 # pump out diffs from before the synch point
2025-07-02 06:41:17.372 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.372
2025-07-02 06:41:17.372 # do intraline marking on the synch pair
2025-07-02 06:41:17.373 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.373 if eqi is None:
2025-07-02 06:41:17.373 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.373 atags = btags = ""
2025-07-02 06:41:17.373 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.373 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.373 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.373 if tag == 'replace':
2025-07-02 06:41:17.373 atags += '^' * la
2025-07-02 06:41:17.373 btags += '^' * lb
2025-07-02 06:41:17.373 elif tag == 'delete':
2025-07-02 06:41:17.373 atags += '-' * la
2025-07-02 06:41:17.373 elif tag == 'insert':
2025-07-02 06:41:17.373 btags += '+' * lb
2025-07-02 06:41:17.373 elif tag == 'equal':
2025-07-02 06:41:17.373 atags += ' ' * la
2025-07-02 06:41:17.373 btags += ' ' * lb
2025-07-02 06:41:17.373 else:
2025-07-02 06:41:17.373 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.373 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.374 else:
2025-07-02 06:41:17.374 # the synch pair is identical
2025-07-02 06:41:17.374 yield ' ' + aelt
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374 # pump out diffs from after the synch point
2025-07-02 06:41:17.374 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.374 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.374 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.374 alo = 218, ahi = 1101
2025-07-02 06:41:17.374 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.374 blo = 218, bhi = 1101
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.374 g = []
2025-07-02 06:41:17.374 if alo < ahi:
2025-07-02 06:41:17.374 if blo < bhi:
2025-07-02 06:41:17.375 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.375 else:
2025-07-02 06:41:17.375 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.375 elif blo < bhi:
2025-07-02 06:41:17.375 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 > yield from g
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.375 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.375 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.375 alo = 218, ahi = 1101
2025-07-02 06:41:17.375 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.375 blo = 218, bhi = 1101
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.375 r"""
2025-07-02 06:41:17.376 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.376 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.376 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.376 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.376
2025-07-02 06:41:17.376 Example:
2025-07-02 06:41:17.376
2025-07-02 06:41:17.376 >>> d = Differ()
2025-07-02 06:41:17.376 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.376 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.376 >>> print(''.join(results), end="")
2025-07-02 06:41:17.376 - abcDefghiJkl
2025-07-02 06:41:17.376 + abcdefGhijkl
2025-07-02 06:41:17.376 """
2025-07-02 06:41:17.376
2025-07-02 06:41:17.376 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.376 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.376 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.377 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.377 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.377
2025-07-02 06:41:17.377 # search for the pair that matches best without being identical
2025-07-02 06:41:17.377 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.377 # on junk -- unless we have to)
2025-07-02 06:41:17.377 for j in range(blo, bhi):
2025-07-02 06:41:17.377 bj = b[j]
2025-07-02 06:41:17.377 cruncher.set_seq2(bj)
2025-07-02 06:41:17.377 for i in range(alo, ahi):
2025-07-02 06:41:17.377 ai = a[i]
2025-07-02 06:41:17.377 if ai == bj:
2025-07-02 06:41:17.377 if eqi is None:
2025-07-02 06:41:17.377 eqi, eqj = i, j
2025-07-02 06:41:17.377 continue
2025-07-02 06:41:17.377 cruncher.set_seq1(ai)
2025-07-02 06:41:17.377 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.377 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.377 # compares by a factor of 3.
2025-07-02 06:41:17.377 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.378 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.378 # of the computation is cached by cruncher
2025-07-02 06:41:17.378 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.378 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.378 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.378 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.378 if best_ratio < cutoff:
2025-07-02 06:41:17.378 # no non-identical "pretty close" pair
2025-07-02 06:41:17.378 if eqi is None:
2025-07-02 06:41:17.378 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.378 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.378 return
2025-07-02 06:41:17.378 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.378 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.378 else:
2025-07-02 06:41:17.378 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.378 eqi = None
2025-07-02 06:41:17.378
2025-07-02 06:41:17.378 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.379 # identical
2025-07-02 06:41:17.379
2025-07-02 06:41:17.379 # pump out diffs from before the synch point
2025-07-02 06:41:17.379 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.379
2025-07-02 06:41:17.379 # do intraline marking on the synch pair
2025-07-02 06:41:17.379 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.379 if eqi is None:
2025-07-02 06:41:17.379 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.379 atags = btags = ""
2025-07-02 06:41:17.379 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.379 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.379 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.379 if tag == 'replace':
2025-07-02 06:41:17.379 atags += '^' * la
2025-07-02 06:41:17.379 btags += '^' * lb
2025-07-02 06:41:17.379 elif tag == 'delete':
2025-07-02 06:41:17.379 atags += '-' * la
2025-07-02 06:41:17.379 elif tag == 'insert':
2025-07-02 06:41:17.380 btags += '+' * lb
2025-07-02 06:41:17.380 elif tag == 'equal':
2025-07-02 06:41:17.380 atags += ' ' * la
2025-07-02 06:41:17.380 btags += ' ' * lb
2025-07-02 06:41:17.380 else:
2025-07-02 06:41:17.380 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.380 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.380 else:
2025-07-02 06:41:17.380 # the synch pair is identical
2025-07-02 06:41:17.380 yield ' ' + aelt
2025-07-02 06:41:17.380
2025-07-02 06:41:17.380 # pump out diffs from after the synch point
2025-07-02 06:41:17.380 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.380
2025-07-02 06:41:17.380 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.380 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.380
2025-07-02 06:41:17.380 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.380 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.381 alo = 219, ahi = 1101
2025-07-02 06:41:17.381 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.381 blo = 219, bhi = 1101
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.381 g = []
2025-07-02 06:41:17.381 if alo < ahi:
2025-07-02 06:41:17.381 if blo < bhi:
2025-07-02 06:41:17.381 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.381 else:
2025-07-02 06:41:17.381 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.381 elif blo < bhi:
2025-07-02 06:41:17.381 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 > yield from g
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.381 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.382 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.382 alo = 219, ahi = 1101
2025-07-02 06:41:17.382 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.382 blo = 219, bhi = 1101
2025-07-02 06:41:17.382
2025-07-02 06:41:17.382 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.382 r"""
2025-07-02 06:41:17.382 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.382 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.382 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.382 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.382
2025-07-02 06:41:17.382 Example:
2025-07-02 06:41:17.382
2025-07-02 06:41:17.382 >>> d = Differ()
2025-07-02 06:41:17.382 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.382 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.382 >>> print(''.join(results), end="")
2025-07-02 06:41:17.382 - abcDefghiJkl
2025-07-02 06:41:17.383 + abcdefGhijkl
2025-07-02 06:41:17.383 """
2025-07-02 06:41:17.383
2025-07-02 06:41:17.383 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.383 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.383 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.383 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.383 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.383
2025-07-02 06:41:17.383 # search for the pair that matches best without being identical
2025-07-02 06:41:17.383 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.383 # on junk -- unless we have to)
2025-07-02 06:41:17.383 for j in range(blo, bhi):
2025-07-02 06:41:17.383 bj = b[j]
2025-07-02 06:41:17.383 cruncher.set_seq2(bj)
2025-07-02 06:41:17.383 for i in range(alo, ahi):
2025-07-02 06:41:17.383 ai = a[i]
2025-07-02 06:41:17.383 if ai == bj:
2025-07-02 06:41:17.383 if eqi is None:
2025-07-02 06:41:17.384 eqi, eqj = i, j
2025-07-02 06:41:17.384 continue
2025-07-02 06:41:17.384 cruncher.set_seq1(ai)
2025-07-02 06:41:17.384 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.384 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.384 # compares by a factor of 3.
2025-07-02 06:41:17.384 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.384 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.384 # of the computation is cached by cruncher
2025-07-02 06:41:17.384 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.384 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.384 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.384 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.384 if best_ratio < cutoff:
2025-07-02 06:41:17.384 # no non-identical "pretty close" pair
2025-07-02 06:41:17.384 if eqi is None:
2025-07-02 06:41:17.384 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.384 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.384 return
2025-07-02 06:41:17.384 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.385 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.385 else:
2025-07-02 06:41:17.385 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.385 eqi = None
2025-07-02 06:41:17.385
2025-07-02 06:41:17.385 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.385 # identical
2025-07-02 06:41:17.385
2025-07-02 06:41:17.385 # pump out diffs from before the synch point
2025-07-02 06:41:17.385 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.385
2025-07-02 06:41:17.385 # do intraline marking on the synch pair
2025-07-02 06:41:17.385 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.385 if eqi is None:
2025-07-02 06:41:17.385 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.385 atags = btags = ""
2025-07-02 06:41:17.385 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.385 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.385 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.386 if tag == 'replace':
2025-07-02 06:41:17.386 atags += '^' * la
2025-07-02 06:41:17.386 btags += '^' * lb
2025-07-02 06:41:17.386 elif tag == 'delete':
2025-07-02 06:41:17.386 atags += '-' * la
2025-07-02 06:41:17.386 elif tag == 'insert':
2025-07-02 06:41:17.386 btags += '+' * lb
2025-07-02 06:41:17.386 elif tag == 'equal':
2025-07-02 06:41:17.386 atags += ' ' * la
2025-07-02 06:41:17.386 btags += ' ' * lb
2025-07-02 06:41:17.386 else:
2025-07-02 06:41:17.386 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.386 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.386 else:
2025-07-02 06:41:17.386 # the synch pair is identical
2025-07-02 06:41:17.386 yield ' ' + aelt
2025-07-02 06:41:17.386
2025-07-02 06:41:17.386 # pump out diffs from after the synch point
2025-07-02 06:41:17.386 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.386
2025-07-02 06:41:17.387 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.387 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.387
2025-07-02 06:41:17.387 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.387 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.387 alo = 220, ahi = 1101
2025-07-02 06:41:17.387 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.387 blo = 220, bhi = 1101
2025-07-02 06:41:17.387
2025-07-02 06:41:17.387 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.387 g = []
2025-07-02 06:41:17.387 if alo < ahi:
2025-07-02 06:41:17.387 if blo < bhi:
2025-07-02 06:41:17.387 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.387 else:
2025-07-02 06:41:17.387 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.387 elif blo < bhi:
2025-07-02 06:41:17.387 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 > yield from g
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.388 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.388 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.388 alo = 220, ahi = 1101
2025-07-02 06:41:17.388 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.388 blo = 220, bhi = 1101
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.388 r"""
2025-07-02 06:41:17.388 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.388 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.388 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.388 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389 Example:
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389 >>> d = Differ()
2025-07-02 06:41:17.389 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.389 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.389 >>> print(''.join(results), end="")
2025-07-02 06:41:17.389 - abcDefghiJkl
2025-07-02 06:41:17.389 + abcdefGhijkl
2025-07-02 06:41:17.389 """
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.389 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.389 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.389 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.389 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389 # search for the pair that matches best without being identical
2025-07-02 06:41:17.390 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.390 # on junk -- unless we have to)
2025-07-02 06:41:17.390 for j in range(blo, bhi):
2025-07-02 06:41:17.390 bj = b[j]
2025-07-02 06:41:17.390 cruncher.set_seq2(bj)
2025-07-02 06:41:17.390 for i in range(alo, ahi):
2025-07-02 06:41:17.390 ai = a[i]
2025-07-02 06:41:17.390 if ai == bj:
2025-07-02 06:41:17.390 if eqi is None:
2025-07-02 06:41:17.390 eqi, eqj = i, j
2025-07-02 06:41:17.390 continue
2025-07-02 06:41:17.390 cruncher.set_seq1(ai)
2025-07-02 06:41:17.390 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.390 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.390 # compares by a factor of 3.
2025-07-02 06:41:17.390 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.390 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.390 # of the computation is cached by cruncher
2025-07-02 06:41:17.390 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.390 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.391 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.391 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.391 if best_ratio < cutoff:
2025-07-02 06:41:17.391 # no non-identical "pretty close" pair
2025-07-02 06:41:17.391 if eqi is None:
2025-07-02 06:41:17.391 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.391 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.391 return
2025-07-02 06:41:17.391 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.391 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.391 else:
2025-07-02 06:41:17.391 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.391 eqi = None
2025-07-02 06:41:17.391
2025-07-02 06:41:17.391 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.391 # identical
2025-07-02 06:41:17.391
2025-07-02 06:41:17.391 # pump out diffs from before the synch point
2025-07-02 06:41:17.391 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.392
2025-07-02 06:41:17.392 # do intraline marking on the synch pair
2025-07-02 06:41:17.392 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.392 if eqi is None:
2025-07-02 06:41:17.392 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.392 atags = btags = ""
2025-07-02 06:41:17.392 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.392 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.392 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.392 if tag == 'replace':
2025-07-02 06:41:17.392 atags += '^' * la
2025-07-02 06:41:17.392 btags += '^' * lb
2025-07-02 06:41:17.392 elif tag == 'delete':
2025-07-02 06:41:17.392 atags += '-' * la
2025-07-02 06:41:17.392 elif tag == 'insert':
2025-07-02 06:41:17.392 btags += '+' * lb
2025-07-02 06:41:17.392 elif tag == 'equal':
2025-07-02 06:41:17.392 atags += ' ' * la
2025-07-02 06:41:17.392 btags += ' ' * lb
2025-07-02 06:41:17.392 else:
2025-07-02 06:41:17.393 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.393 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.393 else:
2025-07-02 06:41:17.393 # the synch pair is identical
2025-07-02 06:41:17.393 yield ' ' + aelt
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393 # pump out diffs from after the synch point
2025-07-02 06:41:17.393 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.393 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.393 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.393 alo = 221, ahi = 1101
2025-07-02 06:41:17.393 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.393 blo = 221, bhi = 1101
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.393 g = []
2025-07-02 06:41:17.394 if alo < ahi:
2025-07-02 06:41:17.394 if blo < bhi:
2025-07-02 06:41:17.394 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.394 else:
2025-07-02 06:41:17.394 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.394 elif blo < bhi:
2025-07-02 06:41:17.394 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 > yield from g
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.394 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.394 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.394 alo = 221, ahi = 1101
2025-07-02 06:41:17.394 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.394 blo = 221, bhi = 1101
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.395 r"""
2025-07-02 06:41:17.395 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.395 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.395 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.395 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.395
2025-07-02 06:41:17.395 Example:
2025-07-02 06:41:17.395
2025-07-02 06:41:17.395 >>> d = Differ()
2025-07-02 06:41:17.395 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.395 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.395 >>> print(''.join(results), end="")
2025-07-02 06:41:17.395 - abcDefghiJkl
2025-07-02 06:41:17.395 + abcdefGhijkl
2025-07-02 06:41:17.395 """
2025-07-02 06:41:17.395
2025-07-02 06:41:17.396 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.396 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.396 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.396 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.396 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.396
2025-07-02 06:41:17.396 # search for the pair that matches best without being identical
2025-07-02 06:41:17.396 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.396 # on junk -- unless we have to)
2025-07-02 06:41:17.396 for j in range(blo, bhi):
2025-07-02 06:41:17.396 bj = b[j]
2025-07-02 06:41:17.396 cruncher.set_seq2(bj)
2025-07-02 06:41:17.396 for i in range(alo, ahi):
2025-07-02 06:41:17.396 ai = a[i]
2025-07-02 06:41:17.396 if ai == bj:
2025-07-02 06:41:17.396 if eqi is None:
2025-07-02 06:41:17.396 eqi, eqj = i, j
2025-07-02 06:41:17.396 continue
2025-07-02 06:41:17.397 cruncher.set_seq1(ai)
2025-07-02 06:41:17.397 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.397 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.397 # compares by a factor of 3.
2025-07-02 06:41:17.397 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.397 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.397 # of the computation is cached by cruncher
2025-07-02 06:41:17.397 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.397 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.397 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.397 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.397 if best_ratio < cutoff:
2025-07-02 06:41:17.397 # no non-identical "pretty close" pair
2025-07-02 06:41:17.397 if eqi is None:
2025-07-02 06:41:17.397 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.397 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.397 return
2025-07-02 06:41:17.397 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.397 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.398 else:
2025-07-02 06:41:17.398 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.398 eqi = None
2025-07-02 06:41:17.398
2025-07-02 06:41:17.398 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.398 # identical
2025-07-02 06:41:17.398
2025-07-02 06:41:17.398 # pump out diffs from before the synch point
2025-07-02 06:41:17.398 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.398
2025-07-02 06:41:17.398 # do intraline marking on the synch pair
2025-07-02 06:41:17.398 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.398 if eqi is None:
2025-07-02 06:41:17.398 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.398 atags = btags = ""
2025-07-02 06:41:17.398 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.398 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.398 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.398 if tag == 'replace':
2025-07-02 06:41:17.398 atags += '^' * la
2025-07-02 06:41:17.399 btags += '^' * lb
2025-07-02 06:41:17.399 elif tag == 'delete':
2025-07-02 06:41:17.399 atags += '-' * la
2025-07-02 06:41:17.399 elif tag == 'insert':
2025-07-02 06:41:17.399 btags += '+' * lb
2025-07-02 06:41:17.399 elif tag == 'equal':
2025-07-02 06:41:17.399 atags += ' ' * la
2025-07-02 06:41:17.399 btags += ' ' * lb
2025-07-02 06:41:17.399 else:
2025-07-02 06:41:17.399 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.399 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.399 else:
2025-07-02 06:41:17.399 # the synch pair is identical
2025-07-02 06:41:17.399 yield ' ' + aelt
2025-07-02 06:41:17.399
2025-07-02 06:41:17.399 # pump out diffs from after the synch point
2025-07-02 06:41:17.399 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.399
2025-07-02 06:41:17.399 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.399 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.399
2025-07-02 06:41:17.400 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.400 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.400 alo = 224, ahi = 1101
2025-07-02 06:41:17.400 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.400 blo = 224, bhi = 1101
2025-07-02 06:41:17.400
2025-07-02 06:41:17.400 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.400 g = []
2025-07-02 06:41:17.400 if alo < ahi:
2025-07-02 06:41:17.400 if blo < bhi:
2025-07-02 06:41:17.400 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.400 else:
2025-07-02 06:41:17.400 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.400 elif blo < bhi:
2025-07-02 06:41:17.400 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.400
2025-07-02 06:41:17.400 > yield from g
2025-07-02 06:41:17.400
2025-07-02 06:41:17.400 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.400 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.401 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.401 alo = 224, ahi = 1101
2025-07-02 06:41:17.401 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.401 blo = 224, bhi = 1101
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.401 r"""
2025-07-02 06:41:17.401 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.401 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.401 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.401 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401 Example:
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401 >>> d = Differ()
2025-07-02 06:41:17.401 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.401 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.401 >>> print(''.join(results), end="")
2025-07-02 06:41:17.402 - abcDefghiJkl
2025-07-02 06:41:17.402 + abcdefGhijkl
2025-07-02 06:41:17.402 """
2025-07-02 06:41:17.402
2025-07-02 06:41:17.402 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.402 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.402 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.402 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.402 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.402
2025-07-02 06:41:17.402 # search for the pair that matches best without being identical
2025-07-02 06:41:17.402 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.402 # on junk -- unless we have to)
2025-07-02 06:41:17.402 for j in range(blo, bhi):
2025-07-02 06:41:17.402 bj = b[j]
2025-07-02 06:41:17.402 cruncher.set_seq2(bj)
2025-07-02 06:41:17.402 for i in range(alo, ahi):
2025-07-02 06:41:17.402 ai = a[i]
2025-07-02 06:41:17.402 if ai == bj:
2025-07-02 06:41:17.403 if eqi is None:
2025-07-02 06:41:17.403 eqi, eqj = i, j
2025-07-02 06:41:17.403 continue
2025-07-02 06:41:17.403 cruncher.set_seq1(ai)
2025-07-02 06:41:17.403 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.403 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.403 # compares by a factor of 3.
2025-07-02 06:41:17.403 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.403 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.403 # of the computation is cached by cruncher
2025-07-02 06:41:17.403 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.403 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.403 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.403 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.403 if best_ratio < cutoff:
2025-07-02 06:41:17.403 # no non-identical "pretty close" pair
2025-07-02 06:41:17.403 if eqi is None:
2025-07-02 06:41:17.403 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.403 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.403 return
2025-07-02 06:41:17.404 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.404 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.404 else:
2025-07-02 06:41:17.404 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.404 eqi = None
2025-07-02 06:41:17.404
2025-07-02 06:41:17.404 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.404 # identical
2025-07-02 06:41:17.404
2025-07-02 06:41:17.404 # pump out diffs from before the synch point
2025-07-02 06:41:17.404 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.404
2025-07-02 06:41:17.404 # do intraline marking on the synch pair
2025-07-02 06:41:17.404 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.404 if eqi is None:
2025-07-02 06:41:17.404 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.404 atags = btags = ""
2025-07-02 06:41:17.404 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.404 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.404 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.405 if tag == 'replace':
2025-07-02 06:41:17.405 atags += '^' * la
2025-07-02 06:41:17.405 btags += '^' * lb
2025-07-02 06:41:17.405 elif tag == 'delete':
2025-07-02 06:41:17.405 atags += '-' * la
2025-07-02 06:41:17.405 elif tag == 'insert':
2025-07-02 06:41:17.405 btags += '+' * lb
2025-07-02 06:41:17.405 elif tag == 'equal':
2025-07-02 06:41:17.405 atags += ' ' * la
2025-07-02 06:41:17.405 btags += ' ' * lb
2025-07-02 06:41:17.405 else:
2025-07-02 06:41:17.405 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.405 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.405 else:
2025-07-02 06:41:17.405 # the synch pair is identical
2025-07-02 06:41:17.405 yield ' ' + aelt
2025-07-02 06:41:17.405
2025-07-02 06:41:17.405 # pump out diffs from after the synch point
2025-07-02 06:41:17.405 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.405
2025-07-02 06:41:17.406 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.406 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.406
2025-07-02 06:41:17.406 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.406 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.406 alo = 225, ahi = 1101
2025-07-02 06:41:17.406 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.406 blo = 225, bhi = 1101
2025-07-02 06:41:17.406
2025-07-02 06:41:17.406 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.406 g = []
2025-07-02 06:41:17.406 if alo < ahi:
2025-07-02 06:41:17.406 if blo < bhi:
2025-07-02 06:41:17.406 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.406 else:
2025-07-02 06:41:17.406 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.406 elif blo < bhi:
2025-07-02 06:41:17.406 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.406
2025-07-02 06:41:17.407 > yield from g
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.407 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.407 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.407 alo = 225, ahi = 1101
2025-07-02 06:41:17.407 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.407 blo = 225, bhi = 1101
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.407 r"""
2025-07-02 06:41:17.407 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.407 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.407 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.407 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407 Example:
2025-07-02 06:41:17.407
2025-07-02 06:41:17.408 >>> d = Differ()
2025-07-02 06:41:17.408 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.408 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.408 >>> print(''.join(results), end="")
2025-07-02 06:41:17.408 - abcDefghiJkl
2025-07-02 06:41:17.408 + abcdefGhijkl
2025-07-02 06:41:17.408 """
2025-07-02 06:41:17.408
2025-07-02 06:41:17.408 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.408 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.408 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.408 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.408 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.408
2025-07-02 06:41:17.408 # search for the pair that matches best without being identical
2025-07-02 06:41:17.408 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.408 # on junk -- unless we have to)
2025-07-02 06:41:17.408 for j in range(blo, bhi):
2025-07-02 06:41:17.408 bj = b[j]
2025-07-02 06:41:17.409 cruncher.set_seq2(bj)
2025-07-02 06:41:17.409 for i in range(alo, ahi):
2025-07-02 06:41:17.409 ai = a[i]
2025-07-02 06:41:17.409 if ai == bj:
2025-07-02 06:41:17.409 if eqi is None:
2025-07-02 06:41:17.409 eqi, eqj = i, j
2025-07-02 06:41:17.409 continue
2025-07-02 06:41:17.409 cruncher.set_seq1(ai)
2025-07-02 06:41:17.409 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.409 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.409 # compares by a factor of 3.
2025-07-02 06:41:17.409 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.409 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.409 # of the computation is cached by cruncher
2025-07-02 06:41:17.409 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.409 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.409 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.409 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.409 if best_ratio < cutoff:
2025-07-02 06:41:17.409 # no non-identical "pretty close" pair
2025-07-02 06:41:17.410 if eqi is None:
2025-07-02 06:41:17.410 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.410 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.410 return
2025-07-02 06:41:17.410 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.410 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.410 else:
2025-07-02 06:41:17.410 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.410 eqi = None
2025-07-02 06:41:17.410
2025-07-02 06:41:17.410 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.410 # identical
2025-07-02 06:41:17.410
2025-07-02 06:41:17.410 # pump out diffs from before the synch point
2025-07-02 06:41:17.410 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.410
2025-07-02 06:41:17.410 # do intraline marking on the synch pair
2025-07-02 06:41:17.410 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.411 if eqi is None:
2025-07-02 06:41:17.411 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.411 atags = btags = ""
2025-07-02 06:41:17.411 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.411 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.411 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.411 if tag == 'replace':
2025-07-02 06:41:17.411 atags += '^' * la
2025-07-02 06:41:17.411 btags += '^' * lb
2025-07-02 06:41:17.411 elif tag == 'delete':
2025-07-02 06:41:17.411 atags += '-' * la
2025-07-02 06:41:17.411 elif tag == 'insert':
2025-07-02 06:41:17.411 btags += '+' * lb
2025-07-02 06:41:17.411 elif tag == 'equal':
2025-07-02 06:41:17.411 atags += ' ' * la
2025-07-02 06:41:17.411 btags += ' ' * lb
2025-07-02 06:41:17.411 else:
2025-07-02 06:41:17.411 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.411 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.411 else:
2025-07-02 06:41:17.412 # the synch pair is identical
2025-07-02 06:41:17.412 yield ' ' + aelt
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412 # pump out diffs from after the synch point
2025-07-02 06:41:17.412 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.412 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.412 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.412 alo = 226, ahi = 1101
2025-07-02 06:41:17.412 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.412 blo = 226, bhi = 1101
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.412 g = []
2025-07-02 06:41:17.412 if alo < ahi:
2025-07-02 06:41:17.412 if blo < bhi:
2025-07-02 06:41:17.412 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.413 else:
2025-07-02 06:41:17.413 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.413 elif blo < bhi:
2025-07-02 06:41:17.413 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 > yield from g
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.413 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.413 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.413 alo = 226, ahi = 1101
2025-07-02 06:41:17.413 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.413 blo = 226, bhi = 1101
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.413 r"""
2025-07-02 06:41:17.414 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.414 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.414 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.414 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.414
2025-07-02 06:41:17.414 Example:
2025-07-02 06:41:17.414
2025-07-02 06:41:17.414 >>> d = Differ()
2025-07-02 06:41:17.414 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.414 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.414 >>> print(''.join(results), end="")
2025-07-02 06:41:17.414 - abcDefghiJkl
2025-07-02 06:41:17.414 + abcdefGhijkl
2025-07-02 06:41:17.414 """
2025-07-02 06:41:17.414
2025-07-02 06:41:17.414 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.414 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.415 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.415 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.415 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.415
2025-07-02 06:41:17.415 # search for the pair that matches best without being identical
2025-07-02 06:41:17.415 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.415 # on junk -- unless we have to)
2025-07-02 06:41:17.415 for j in range(blo, bhi):
2025-07-02 06:41:17.415 bj = b[j]
2025-07-02 06:41:17.415 cruncher.set_seq2(bj)
2025-07-02 06:41:17.415 for i in range(alo, ahi):
2025-07-02 06:41:17.415 ai = a[i]
2025-07-02 06:41:17.415 if ai == bj:
2025-07-02 06:41:17.415 if eqi is None:
2025-07-02 06:41:17.415 eqi, eqj = i, j
2025-07-02 06:41:17.415 continue
2025-07-02 06:41:17.415 cruncher.set_seq1(ai)
2025-07-02 06:41:17.415 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.415 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.415 # compares by a factor of 3.
2025-07-02 06:41:17.416 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.416 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.416 # of the computation is cached by cruncher
2025-07-02 06:41:17.416 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.416 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.416 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.416 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.416 if best_ratio < cutoff:
2025-07-02 06:41:17.416 # no non-identical "pretty close" pair
2025-07-02 06:41:17.416 if eqi is None:
2025-07-02 06:41:17.416 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.416 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.416 return
2025-07-02 06:41:17.416 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.416 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.416 else:
2025-07-02 06:41:17.416 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.416 eqi = None
2025-07-02 06:41:17.416
2025-07-02 06:41:17.416 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.417 # identical
2025-07-02 06:41:17.417
2025-07-02 06:41:17.417 # pump out diffs from before the synch point
2025-07-02 06:41:17.417 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.417
2025-07-02 06:41:17.417 # do intraline marking on the synch pair
2025-07-02 06:41:17.417 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.417 if eqi is None:
2025-07-02 06:41:17.417 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.417 atags = btags = ""
2025-07-02 06:41:17.417 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.417 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.417 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.417 if tag == 'replace':
2025-07-02 06:41:17.417 atags += '^' * la
2025-07-02 06:41:17.417 btags += '^' * lb
2025-07-02 06:41:17.417 elif tag == 'delete':
2025-07-02 06:41:17.417 atags += '-' * la
2025-07-02 06:41:17.417 elif tag == 'insert':
2025-07-02 06:41:17.417 btags += '+' * lb
2025-07-02 06:41:17.418 elif tag == 'equal':
2025-07-02 06:41:17.418 atags += ' ' * la
2025-07-02 06:41:17.418 btags += ' ' * lb
2025-07-02 06:41:17.418 else:
2025-07-02 06:41:17.418 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.418 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.418 else:
2025-07-02 06:41:17.418 # the synch pair is identical
2025-07-02 06:41:17.418 yield ' ' + aelt
2025-07-02 06:41:17.418
2025-07-02 06:41:17.418 # pump out diffs from after the synch point
2025-07-02 06:41:17.418 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.418
2025-07-02 06:41:17.418 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.418 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.418
2025-07-02 06:41:17.418 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.418 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.418 alo = 227, ahi = 1101
2025-07-02 06:41:17.418 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.419 blo = 227, bhi = 1101
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.419 g = []
2025-07-02 06:41:17.419 if alo < ahi:
2025-07-02 06:41:17.419 if blo < bhi:
2025-07-02 06:41:17.419 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.419 else:
2025-07-02 06:41:17.419 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.419 elif blo < bhi:
2025-07-02 06:41:17.419 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 > yield from g
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.419 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.419 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.419 alo = 227, ahi = 1101
2025-07-02 06:41:17.419 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.420 blo = 227, bhi = 1101
2025-07-02 06:41:17.420
2025-07-02 06:41:17.420 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.420 r"""
2025-07-02 06:41:17.420 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.420 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.420 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.420 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.420
2025-07-02 06:41:17.420 Example:
2025-07-02 06:41:17.420
2025-07-02 06:41:17.420 >>> d = Differ()
2025-07-02 06:41:17.420 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.420 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.420 >>> print(''.join(results), end="")
2025-07-02 06:41:17.420 - abcDefghiJkl
2025-07-02 06:41:17.420 + abcdefGhijkl
2025-07-02 06:41:17.420 """
2025-07-02 06:41:17.421
2025-07-02 06:41:17.421 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.421 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.421 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.421 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.421 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.421
2025-07-02 06:41:17.421 # search for the pair that matches best without being identical
2025-07-02 06:41:17.421 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.421 # on junk -- unless we have to)
2025-07-02 06:41:17.421 for j in range(blo, bhi):
2025-07-02 06:41:17.421 bj = b[j]
2025-07-02 06:41:17.421 cruncher.set_seq2(bj)
2025-07-02 06:41:17.421 for i in range(alo, ahi):
2025-07-02 06:41:17.421 ai = a[i]
2025-07-02 06:41:17.421 if ai == bj:
2025-07-02 06:41:17.421 if eqi is None:
2025-07-02 06:41:17.421 eqi, eqj = i, j
2025-07-02 06:41:17.421 continue
2025-07-02 06:41:17.421 cruncher.set_seq1(ai)
2025-07-02 06:41:17.422 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.422 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.422 # compares by a factor of 3.
2025-07-02 06:41:17.422 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.422 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.422 # of the computation is cached by cruncher
2025-07-02 06:41:17.422 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.422 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.422 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.422 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.422 if best_ratio < cutoff:
2025-07-02 06:41:17.422 # no non-identical "pretty close" pair
2025-07-02 06:41:17.422 if eqi is None:
2025-07-02 06:41:17.422 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.422 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.422 return
2025-07-02 06:41:17.422 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.422 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.423 else:
2025-07-02 06:41:17.423 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.423 eqi = None
2025-07-02 06:41:17.423
2025-07-02 06:41:17.423 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.423 # identical
2025-07-02 06:41:17.423
2025-07-02 06:41:17.423 # pump out diffs from before the synch point
2025-07-02 06:41:17.423 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.423
2025-07-02 06:41:17.423 # do intraline marking on the synch pair
2025-07-02 06:41:17.423 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.423 if eqi is None:
2025-07-02 06:41:17.423 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.423 atags = btags = ""
2025-07-02 06:41:17.423 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.423 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.423 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.423 if tag == 'replace':
2025-07-02 06:41:17.424 atags += '^' * la
2025-07-02 06:41:17.424 btags += '^' * lb
2025-07-02 06:41:17.424 elif tag == 'delete':
2025-07-02 06:41:17.424 atags += '-' * la
2025-07-02 06:41:17.424 elif tag == 'insert':
2025-07-02 06:41:17.424 btags += '+' * lb
2025-07-02 06:41:17.424 elif tag == 'equal':
2025-07-02 06:41:17.424 atags += ' ' * la
2025-07-02 06:41:17.424 btags += ' ' * lb
2025-07-02 06:41:17.424 else:
2025-07-02 06:41:17.424 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.424 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.424 else:
2025-07-02 06:41:17.424 # the synch pair is identical
2025-07-02 06:41:17.424 yield ' ' + aelt
2025-07-02 06:41:17.424
2025-07-02 06:41:17.424 # pump out diffs from after the synch point
2025-07-02 06:41:17.424 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.424
2025-07-02 06:41:17.424 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.425 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.425
2025-07-02 06:41:17.425 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.425 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.425 alo = 228, ahi = 1101
2025-07-02 06:41:17.425 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.425 blo = 228, bhi = 1101
2025-07-02 06:41:17.425
2025-07-02 06:41:17.425 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.425 g = []
2025-07-02 06:41:17.425 if alo < ahi:
2025-07-02 06:41:17.425 if blo < bhi:
2025-07-02 06:41:17.425 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.425 else:
2025-07-02 06:41:17.425 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.425 elif blo < bhi:
2025-07-02 06:41:17.425 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.425
2025-07-02 06:41:17.425 > yield from g
2025-07-02 06:41:17.425
2025-07-02 06:41:17.426 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.426 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.426
2025-07-02 06:41:17.426 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.426 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.426 alo = 228, ahi = 1101
2025-07-02 06:41:17.426 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.426 blo = 228, bhi = 1101
2025-07-02 06:41:17.426
2025-07-02 06:41:17.426 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.426 r"""
2025-07-02 06:41:17.426 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.426 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.426 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.426 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.426
2025-07-02 06:41:17.426 Example:
2025-07-02 06:41:17.426
2025-07-02 06:41:17.427 >>> d = Differ()
2025-07-02 06:41:17.427 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.427 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.427 >>> print(''.join(results), end="")
2025-07-02 06:41:17.427 - abcDefghiJkl
2025-07-02 06:41:17.427 + abcdefGhijkl
2025-07-02 06:41:17.427 """
2025-07-02 06:41:17.427
2025-07-02 06:41:17.427 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.427 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.427 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.427 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.427 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.427
2025-07-02 06:41:17.427 # search for the pair that matches best without being identical
2025-07-02 06:41:17.427 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.427 # on junk -- unless we have to)
2025-07-02 06:41:17.427 for j in range(blo, bhi):
2025-07-02 06:41:17.428 bj = b[j]
2025-07-02 06:41:17.428 cruncher.set_seq2(bj)
2025-07-02 06:41:17.428 for i in range(alo, ahi):
2025-07-02 06:41:17.428 ai = a[i]
2025-07-02 06:41:17.428 if ai == bj:
2025-07-02 06:41:17.428 if eqi is None:
2025-07-02 06:41:17.428 eqi, eqj = i, j
2025-07-02 06:41:17.428 continue
2025-07-02 06:41:17.428 cruncher.set_seq1(ai)
2025-07-02 06:41:17.428 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.428 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.428 # compares by a factor of 3.
2025-07-02 06:41:17.428 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.428 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.428 # of the computation is cached by cruncher
2025-07-02 06:41:17.428 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.428 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.428 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.428 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.428 if best_ratio < cutoff:
2025-07-02 06:41:17.429 # no non-identical "pretty close" pair
2025-07-02 06:41:17.429 if eqi is None:
2025-07-02 06:41:17.429 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.429 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.429 return
2025-07-02 06:41:17.429 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.429 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.429 else:
2025-07-02 06:41:17.429 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.429 eqi = None
2025-07-02 06:41:17.429
2025-07-02 06:41:17.429 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.429 # identical
2025-07-02 06:41:17.429
2025-07-02 06:41:17.429 # pump out diffs from before the synch point
2025-07-02 06:41:17.429 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.429
2025-07-02 06:41:17.429 # do intraline marking on the synch pair
2025-07-02 06:41:17.429 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.429 if eqi is None:
2025-07-02 06:41:17.430 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.430 atags = btags = ""
2025-07-02 06:41:17.430 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.430 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.430 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.430 if tag == 'replace':
2025-07-02 06:41:17.430 atags += '^' * la
2025-07-02 06:41:17.430 btags += '^' * lb
2025-07-02 06:41:17.430 elif tag == 'delete':
2025-07-02 06:41:17.430 atags += '-' * la
2025-07-02 06:41:17.430 elif tag == 'insert':
2025-07-02 06:41:17.430 btags += '+' * lb
2025-07-02 06:41:17.430 elif tag == 'equal':
2025-07-02 06:41:17.430 atags += ' ' * la
2025-07-02 06:41:17.430 btags += ' ' * lb
2025-07-02 06:41:17.430 else:
2025-07-02 06:41:17.430 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.430 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.430 else:
2025-07-02 06:41:17.431 # the synch pair is identical
2025-07-02 06:41:17.431 yield ' ' + aelt
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431 # pump out diffs from after the synch point
2025-07-02 06:41:17.431 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.431 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.431 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.431 alo = 229, ahi = 1101
2025-07-02 06:41:17.431 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.431 blo = 229, bhi = 1101
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.431 g = []
2025-07-02 06:41:17.432 if alo < ahi:
2025-07-02 06:41:17.432 if blo < bhi:
2025-07-02 06:41:17.432 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.432 else:
2025-07-02 06:41:17.432 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.432 elif blo < bhi:
2025-07-02 06:41:17.432 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.432
2025-07-02 06:41:17.432 > yield from g
2025-07-02 06:41:17.432
2025-07-02 06:41:17.432 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.432 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.432
2025-07-02 06:41:17.432 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.432 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.432 alo = 229, ahi = 1101
2025-07-02 06:41:17.432 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.432 blo = 229, bhi = 1101
2025-07-02 06:41:17.432
2025-07-02 06:41:17.433 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.433 r"""
2025-07-02 06:41:17.433 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.433 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.433 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.433 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.433
2025-07-02 06:41:17.433 Example:
2025-07-02 06:41:17.433
2025-07-02 06:41:17.433 >>> d = Differ()
2025-07-02 06:41:17.433 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.433 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.433 >>> print(''.join(results), end="")
2025-07-02 06:41:17.433 - abcDefghiJkl
2025-07-02 06:41:17.433 + abcdefGhijkl
2025-07-02 06:41:17.433 """
2025-07-02 06:41:17.433
2025-07-02 06:41:17.433 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.434 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.434 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.434 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.434 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.434
2025-07-02 06:41:17.434 # search for the pair that matches best without being identical
2025-07-02 06:41:17.434 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.434 # on junk -- unless we have to)
2025-07-02 06:41:17.434 for j in range(blo, bhi):
2025-07-02 06:41:17.434 bj = b[j]
2025-07-02 06:41:17.434 cruncher.set_seq2(bj)
2025-07-02 06:41:17.434 for i in range(alo, ahi):
2025-07-02 06:41:17.434 ai = a[i]
2025-07-02 06:41:17.434 if ai == bj:
2025-07-02 06:41:17.434 if eqi is None:
2025-07-02 06:41:17.434 eqi, eqj = i, j
2025-07-02 06:41:17.434 continue
2025-07-02 06:41:17.434 cruncher.set_seq1(ai)
2025-07-02 06:41:17.434 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.434 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.435 # compares by a factor of 3.
2025-07-02 06:41:17.435 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.435 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.435 # of the computation is cached by cruncher
2025-07-02 06:41:17.435 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.435 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.435 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.435 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.435 if best_ratio < cutoff:
2025-07-02 06:41:17.435 # no non-identical "pretty close" pair
2025-07-02 06:41:17.435 if eqi is None:
2025-07-02 06:41:17.435 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.435 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.435 return
2025-07-02 06:41:17.435 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.435 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.435 else:
2025-07-02 06:41:17.436 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.436 eqi = None
2025-07-02 06:41:17.436
2025-07-02 06:41:17.436 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.436 # identical
2025-07-02 06:41:17.436
2025-07-02 06:41:17.436 # pump out diffs from before the synch point
2025-07-02 06:41:17.436 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.436
2025-07-02 06:41:17.436 # do intraline marking on the synch pair
2025-07-02 06:41:17.436 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.436 if eqi is None:
2025-07-02 06:41:17.436 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.436 atags = btags = ""
2025-07-02 06:41:17.436 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.436 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.436 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.436 if tag == 'replace':
2025-07-02 06:41:17.436 atags += '^' * la
2025-07-02 06:41:17.437 btags += '^' * lb
2025-07-02 06:41:17.437 elif tag == 'delete':
2025-07-02 06:41:17.437 atags += '-' * la
2025-07-02 06:41:17.437 elif tag == 'insert':
2025-07-02 06:41:17.437 btags += '+' * lb
2025-07-02 06:41:17.437 elif tag == 'equal':
2025-07-02 06:41:17.437 atags += ' ' * la
2025-07-02 06:41:17.437 btags += ' ' * lb
2025-07-02 06:41:17.437 else:
2025-07-02 06:41:17.437 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.437 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.437 else:
2025-07-02 06:41:17.437 # the synch pair is identical
2025-07-02 06:41:17.437 yield ' ' + aelt
2025-07-02 06:41:17.437
2025-07-02 06:41:17.437 # pump out diffs from after the synch point
2025-07-02 06:41:17.437 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.437
2025-07-02 06:41:17.437 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.438 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.438
2025-07-02 06:41:17.438 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.438 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.438 alo = 230, ahi = 1101
2025-07-02 06:41:17.438 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.438 blo = 230, bhi = 1101
2025-07-02 06:41:17.438
2025-07-02 06:41:17.438 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.438 g = []
2025-07-02 06:41:17.438 if alo < ahi:
2025-07-02 06:41:17.438 if blo < bhi:
2025-07-02 06:41:17.438 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.438 else:
2025-07-02 06:41:17.438 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.438 elif blo < bhi:
2025-07-02 06:41:17.438 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.438
2025-07-02 06:41:17.438 > yield from g
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.439 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.439 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.439 alo = 230, ahi = 1101
2025-07-02 06:41:17.439 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.439 blo = 230, bhi = 1101
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.439 r"""
2025-07-02 06:41:17.439 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.439 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.439 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.439 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 Example:
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 >>> d = Differ()
2025-07-02 06:41:17.440 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.440 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.440 >>> print(''.join(results), end="")
2025-07-02 06:41:17.440 - abcDefghiJkl
2025-07-02 06:41:17.440 + abcdefGhijkl
2025-07-02 06:41:17.440 """
2025-07-02 06:41:17.440
2025-07-02 06:41:17.440 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.440 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.440 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.440 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.440 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.440
2025-07-02 06:41:17.440 # search for the pair that matches best without being identical
2025-07-02 06:41:17.440 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.440 # on junk -- unless we have to)
2025-07-02 06:41:17.441 for j in range(blo, bhi):
2025-07-02 06:41:17.441 bj = b[j]
2025-07-02 06:41:17.441 cruncher.set_seq2(bj)
2025-07-02 06:41:17.441 for i in range(alo, ahi):
2025-07-02 06:41:17.441 ai = a[i]
2025-07-02 06:41:17.441 if ai == bj:
2025-07-02 06:41:17.441 if eqi is None:
2025-07-02 06:41:17.441 eqi, eqj = i, j
2025-07-02 06:41:17.441 continue
2025-07-02 06:41:17.441 cruncher.set_seq1(ai)
2025-07-02 06:41:17.441 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.441 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.441 # compares by a factor of 3.
2025-07-02 06:41:17.441 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.441 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.441 # of the computation is cached by cruncher
2025-07-02 06:41:17.441 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.442 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.442 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.442 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.442 if best_ratio < cutoff:
2025-07-02 06:41:17.442 # no non-identical "pretty close" pair
2025-07-02 06:41:17.442 if eqi is None:
2025-07-02 06:41:17.442 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.442 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.442 return
2025-07-02 06:41:17.442 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.442 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.442 else:
2025-07-02 06:41:17.442 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.442 eqi = None
2025-07-02 06:41:17.442
2025-07-02 06:41:17.442 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.442 # identical
2025-07-02 06:41:17.442
2025-07-02 06:41:17.442 # pump out diffs from before the synch point
2025-07-02 06:41:17.443 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.443
2025-07-02 06:41:17.443 # do intraline marking on the synch pair
2025-07-02 06:41:17.443 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.443 if eqi is None:
2025-07-02 06:41:17.443 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.443 atags = btags = ""
2025-07-02 06:41:17.443 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.443 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.443 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.443 if tag == 'replace':
2025-07-02 06:41:17.443 atags += '^' * la
2025-07-02 06:41:17.443 btags += '^' * lb
2025-07-02 06:41:17.443 elif tag == 'delete':
2025-07-02 06:41:17.443 atags += '-' * la
2025-07-02 06:41:17.443 elif tag == 'insert':
2025-07-02 06:41:17.443 btags += '+' * lb
2025-07-02 06:41:17.444 elif tag == 'equal':
2025-07-02 06:41:17.444 atags += ' ' * la
2025-07-02 06:41:17.444 btags += ' ' * lb
2025-07-02 06:41:17.444 else:
2025-07-02 06:41:17.444 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.444 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.444 else:
2025-07-02 06:41:17.444 # the synch pair is identical
2025-07-02 06:41:17.444 yield ' ' + aelt
2025-07-02 06:41:17.444
2025-07-02 06:41:17.444 # pump out diffs from after the synch point
2025-07-02 06:41:17.444 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.444
2025-07-02 06:41:17.444 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.444 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.444
2025-07-02 06:41:17.444 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.444 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.444 alo = 231, ahi = 1101
2025-07-02 06:41:17.445 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.445 blo = 231, bhi = 1101
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.445 g = []
2025-07-02 06:41:17.445 if alo < ahi:
2025-07-02 06:41:17.445 if blo < bhi:
2025-07-02 06:41:17.445 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.445 else:
2025-07-02 06:41:17.445 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.445 elif blo < bhi:
2025-07-02 06:41:17.445 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 > yield from g
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.445 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.445 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.446 alo = 231, ahi = 1101
2025-07-02 06:41:17.446 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.446 blo = 231, bhi = 1101
2025-07-02 06:41:17.446
2025-07-02 06:41:17.446 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.446 r"""
2025-07-02 06:41:17.446 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.446 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.446 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.446 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.446
2025-07-02 06:41:17.446 Example:
2025-07-02 06:41:17.446
2025-07-02 06:41:17.446 >>> d = Differ()
2025-07-02 06:41:17.446 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.446 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.446 >>> print(''.join(results), end="")
2025-07-02 06:41:17.446 - abcDefghiJkl
2025-07-02 06:41:17.447 + abcdefGhijkl
2025-07-02 06:41:17.447 """
2025-07-02 06:41:17.447
2025-07-02 06:41:17.447 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.447 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.447 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.447 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.447 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.447
2025-07-02 06:41:17.447 # search for the pair that matches best without being identical
2025-07-02 06:41:17.447 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.447 # on junk -- unless we have to)
2025-07-02 06:41:17.447 for j in range(blo, bhi):
2025-07-02 06:41:17.447 bj = b[j]
2025-07-02 06:41:17.447 cruncher.set_seq2(bj)
2025-07-02 06:41:17.447 for i in range(alo, ahi):
2025-07-02 06:41:17.447 ai = a[i]
2025-07-02 06:41:17.447 if ai == bj:
2025-07-02 06:41:17.447 if eqi is None:
2025-07-02 06:41:17.448 eqi, eqj = i, j
2025-07-02 06:41:17.448 continue
2025-07-02 06:41:17.448 cruncher.set_seq1(ai)
2025-07-02 06:41:17.448 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.448 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.448 # compares by a factor of 3.
2025-07-02 06:41:17.448 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.448 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.448 # of the computation is cached by cruncher
2025-07-02 06:41:17.448 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.448 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.448 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.448 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.448 if best_ratio < cutoff:
2025-07-02 06:41:17.448 # no non-identical "pretty close" pair
2025-07-02 06:41:17.448 if eqi is None:
2025-07-02 06:41:17.448 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.448 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.448 return
2025-07-02 06:41:17.448 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.449 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.449 else:
2025-07-02 06:41:17.449 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.449 eqi = None
2025-07-02 06:41:17.449
2025-07-02 06:41:17.449 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.449 # identical
2025-07-02 06:41:17.449
2025-07-02 06:41:17.449 # pump out diffs from before the synch point
2025-07-02 06:41:17.449 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.449
2025-07-02 06:41:17.449 # do intraline marking on the synch pair
2025-07-02 06:41:17.449 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.449 if eqi is None:
2025-07-02 06:41:17.449 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.449 atags = btags = ""
2025-07-02 06:41:17.449 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.450 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.450 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.450 if tag == 'replace':
2025-07-02 06:41:17.450 atags += '^' * la
2025-07-02 06:41:17.450 btags += '^' * lb
2025-07-02 06:41:17.450 elif tag == 'delete':
2025-07-02 06:41:17.450 atags += '-' * la
2025-07-02 06:41:17.450 elif tag == 'insert':
2025-07-02 06:41:17.450 btags += '+' * lb
2025-07-02 06:41:17.450 elif tag == 'equal':
2025-07-02 06:41:17.450 atags += ' ' * la
2025-07-02 06:41:17.450 btags += ' ' * lb
2025-07-02 06:41:17.450 else:
2025-07-02 06:41:17.450 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.450 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.450 else:
2025-07-02 06:41:17.450 # the synch pair is identical
2025-07-02 06:41:17.450 yield ' ' + aelt
2025-07-02 06:41:17.450
2025-07-02 06:41:17.451 # pump out diffs from after the synch point
2025-07-02 06:41:17.451 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.451
2025-07-02 06:41:17.451 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.451 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.451
2025-07-02 06:41:17.451 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.451 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.451 alo = 232, ahi = 1101
2025-07-02 06:41:17.451 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.451 blo = 232, bhi = 1101
2025-07-02 06:41:17.451
2025-07-02 06:41:17.451 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.451 g = []
2025-07-02 06:41:17.451 if alo < ahi:
2025-07-02 06:41:17.451 if blo < bhi:
2025-07-02 06:41:17.451 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.451 else:
2025-07-02 06:41:17.451 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.452 elif blo < bhi:
2025-07-02 06:41:17.452 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 > yield from g
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.452 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.452 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.452 alo = 232, ahi = 1101
2025-07-02 06:41:17.452 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.452 blo = 232, bhi = 1101
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.452 r"""
2025-07-02 06:41:17.452 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.452 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.452 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.453 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.453
2025-07-02 06:41:17.453 Example:
2025-07-02 06:41:17.453
2025-07-02 06:41:17.453 >>> d = Differ()
2025-07-02 06:41:17.453 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.453 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.453 >>> print(''.join(results), end="")
2025-07-02 06:41:17.453 - abcDefghiJkl
2025-07-02 06:41:17.453 + abcdefGhijkl
2025-07-02 06:41:17.453 """
2025-07-02 06:41:17.453
2025-07-02 06:41:17.453 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.453 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.453 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.453 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.453 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.453
2025-07-02 06:41:17.454 # search for the pair that matches best without being identical
2025-07-02 06:41:17.454 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.454 # on junk -- unless we have to)
2025-07-02 06:41:17.454 for j in range(blo, bhi):
2025-07-02 06:41:17.454 bj = b[j]
2025-07-02 06:41:17.454 cruncher.set_seq2(bj)
2025-07-02 06:41:17.454 for i in range(alo, ahi):
2025-07-02 06:41:17.454 ai = a[i]
2025-07-02 06:41:17.454 if ai == bj:
2025-07-02 06:41:17.454 if eqi is None:
2025-07-02 06:41:17.454 eqi, eqj = i, j
2025-07-02 06:41:17.454 continue
2025-07-02 06:41:17.454 cruncher.set_seq1(ai)
2025-07-02 06:41:17.454 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.454 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.454 # compares by a factor of 3.
2025-07-02 06:41:17.454 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.454 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.454 # of the computation is cached by cruncher
2025-07-02 06:41:17.455 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.455 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.455 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.455 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.455 if best_ratio < cutoff:
2025-07-02 06:41:17.455 # no non-identical "pretty close" pair
2025-07-02 06:41:17.455 if eqi is None:
2025-07-02 06:41:17.455 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.455 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.455 return
2025-07-02 06:41:17.455 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.455 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.455 else:
2025-07-02 06:41:17.455 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.455 eqi = None
2025-07-02 06:41:17.455
2025-07-02 06:41:17.455 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.455 # identical
2025-07-02 06:41:17.455
2025-07-02 06:41:17.455 # pump out diffs from before the synch point
2025-07-02 06:41:17.456 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.456
2025-07-02 06:41:17.456 # do intraline marking on the synch pair
2025-07-02 06:41:17.456 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.456 if eqi is None:
2025-07-02 06:41:17.456 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.456 atags = btags = ""
2025-07-02 06:41:17.456 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.456 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.456 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.456 if tag == 'replace':
2025-07-02 06:41:17.456 atags += '^' * la
2025-07-02 06:41:17.456 btags += '^' * lb
2025-07-02 06:41:17.456 elif tag == 'delete':
2025-07-02 06:41:17.456 atags += '-' * la
2025-07-02 06:41:17.456 elif tag == 'insert':
2025-07-02 06:41:17.456 btags += '+' * lb
2025-07-02 06:41:17.456 elif tag == 'equal':
2025-07-02 06:41:17.456 atags += ' ' * la
2025-07-02 06:41:17.457 btags += ' ' * lb
2025-07-02 06:41:17.457 else:
2025-07-02 06:41:17.457 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.457 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.457 else:
2025-07-02 06:41:17.457 # the synch pair is identical
2025-07-02 06:41:17.457 yield ' ' + aelt
2025-07-02 06:41:17.457
2025-07-02 06:41:17.457 # pump out diffs from after the synch point
2025-07-02 06:41:17.457 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.457
2025-07-02 06:41:17.457 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.457 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.457
2025-07-02 06:41:17.457 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.457 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.457 alo = 233, ahi = 1101
2025-07-02 06:41:17.457 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.458 blo = 233, bhi = 1101
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.458 g = []
2025-07-02 06:41:17.458 if alo < ahi:
2025-07-02 06:41:17.458 if blo < bhi:
2025-07-02 06:41:17.458 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.458 else:
2025-07-02 06:41:17.458 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.458 elif blo < bhi:
2025-07-02 06:41:17.458 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 > yield from g
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.458 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.458 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.459 alo = 233, ahi = 1101
2025-07-02 06:41:17.459 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.459 blo = 233, bhi = 1101
2025-07-02 06:41:17.459
2025-07-02 06:41:17.459 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.459 r"""
2025-07-02 06:41:17.459 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.459 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.459 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.459 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.459
2025-07-02 06:41:17.459 Example:
2025-07-02 06:41:17.459
2025-07-02 06:41:17.459 >>> d = Differ()
2025-07-02 06:41:17.459 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.459 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.459 >>> print(''.join(results), end="")
2025-07-02 06:41:17.459 - abcDefghiJkl
2025-07-02 06:41:17.460 + abcdefGhijkl
2025-07-02 06:41:17.460 """
2025-07-02 06:41:17.460
2025-07-02 06:41:17.460 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.460 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.460 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.460 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.460 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.460
2025-07-02 06:41:17.460 # search for the pair that matches best without being identical
2025-07-02 06:41:17.460 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.460 # on junk -- unless we have to)
2025-07-02 06:41:17.460 for j in range(blo, bhi):
2025-07-02 06:41:17.460 bj = b[j]
2025-07-02 06:41:17.460 cruncher.set_seq2(bj)
2025-07-02 06:41:17.460 for i in range(alo, ahi):
2025-07-02 06:41:17.460 ai = a[i]
2025-07-02 06:41:17.461 if ai == bj:
2025-07-02 06:41:17.461 if eqi is None:
2025-07-02 06:41:17.461 eqi, eqj = i, j
2025-07-02 06:41:17.461 continue
2025-07-02 06:41:17.461 cruncher.set_seq1(ai)
2025-07-02 06:41:17.461 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.461 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.461 # compares by a factor of 3.
2025-07-02 06:41:17.461 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.461 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.461 # of the computation is cached by cruncher
2025-07-02 06:41:17.461 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.461 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.461 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.461 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.461 if best_ratio < cutoff:
2025-07-02 06:41:17.461 # no non-identical "pretty close" pair
2025-07-02 06:41:17.461 if eqi is None:
2025-07-02 06:41:17.461 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.461 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.462 return
2025-07-02 06:41:17.462 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.462 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.462 else:
2025-07-02 06:41:17.462 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.462 eqi = None
2025-07-02 06:41:17.462
2025-07-02 06:41:17.462 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.462 # identical
2025-07-02 06:41:17.462
2025-07-02 06:41:17.462 # pump out diffs from before the synch point
2025-07-02 06:41:17.462 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.462
2025-07-02 06:41:17.462 # do intraline marking on the synch pair
2025-07-02 06:41:17.462 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.462 if eqi is None:
2025-07-02 06:41:17.462 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.462 atags = btags = ""
2025-07-02 06:41:17.463 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.463 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.463 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.463 if tag == 'replace':
2025-07-02 06:41:17.463 atags += '^' * la
2025-07-02 06:41:17.463 btags += '^' * lb
2025-07-02 06:41:17.463 elif tag == 'delete':
2025-07-02 06:41:17.463 atags += '-' * la
2025-07-02 06:41:17.463 elif tag == 'insert':
2025-07-02 06:41:17.463 btags += '+' * lb
2025-07-02 06:41:17.463 elif tag == 'equal':
2025-07-02 06:41:17.463 atags += ' ' * la
2025-07-02 06:41:17.463 btags += ' ' * lb
2025-07-02 06:41:17.463 else:
2025-07-02 06:41:17.463 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.463 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.463 else:
2025-07-02 06:41:17.463 # the synch pair is identical
2025-07-02 06:41:17.463 yield ' ' + aelt
2025-07-02 06:41:17.463
2025-07-02 06:41:17.464 # pump out diffs from after the synch point
2025-07-02 06:41:17.464 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.464
2025-07-02 06:41:17.464 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.464 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.464
2025-07-02 06:41:17.464 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.464 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.464 alo = 234, ahi = 1101
2025-07-02 06:41:17.464 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.464 blo = 234, bhi = 1101
2025-07-02 06:41:17.464
2025-07-02 06:41:17.464 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.464 g = []
2025-07-02 06:41:17.464 if alo < ahi:
2025-07-02 06:41:17.464 if blo < bhi:
2025-07-02 06:41:17.464 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.464 else:
2025-07-02 06:41:17.464 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.465 elif blo < bhi:
2025-07-02 06:41:17.465 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 > yield from g
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.465 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.465 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.465 alo = 234, ahi = 1101
2025-07-02 06:41:17.465 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.465 blo = 234, bhi = 1101
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.465 r"""
2025-07-02 06:41:17.465 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.465 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.465 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.466 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.466
2025-07-02 06:41:17.466 Example:
2025-07-02 06:41:17.466
2025-07-02 06:41:17.466 >>> d = Differ()
2025-07-02 06:41:17.466 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.466 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.466 >>> print(''.join(results), end="")
2025-07-02 06:41:17.466 - abcDefghiJkl
2025-07-02 06:41:17.466 + abcdefGhijkl
2025-07-02 06:41:17.466 """
2025-07-02 06:41:17.466
2025-07-02 06:41:17.466 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.466 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.466 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.466 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.466 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.466
2025-07-02 06:41:17.467 # search for the pair that matches best without being identical
2025-07-02 06:41:17.467 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.467 # on junk -- unless we have to)
2025-07-02 06:41:17.467 for j in range(blo, bhi):
2025-07-02 06:41:17.467 bj = b[j]
2025-07-02 06:41:17.467 cruncher.set_seq2(bj)
2025-07-02 06:41:17.467 for i in range(alo, ahi):
2025-07-02 06:41:17.467 ai = a[i]
2025-07-02 06:41:17.467 if ai == bj:
2025-07-02 06:41:17.467 if eqi is None:
2025-07-02 06:41:17.467 eqi, eqj = i, j
2025-07-02 06:41:17.467 continue
2025-07-02 06:41:17.467 cruncher.set_seq1(ai)
2025-07-02 06:41:17.467 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.467 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.467 # compares by a factor of 3.
2025-07-02 06:41:17.467 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.467 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.468 # of the computation is cached by cruncher
2025-07-02 06:41:17.468 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.468 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.468 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.468 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.468 if best_ratio < cutoff:
2025-07-02 06:41:17.468 # no non-identical "pretty close" pair
2025-07-02 06:41:17.468 if eqi is None:
2025-07-02 06:41:17.468 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.468 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.468 return
2025-07-02 06:41:17.468 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.468 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.468 else:
2025-07-02 06:41:17.468 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.468 eqi = None
2025-07-02 06:41:17.468
2025-07-02 06:41:17.468 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.468 # identical
2025-07-02 06:41:17.469
2025-07-02 06:41:17.469 # pump out diffs from before the synch point
2025-07-02 06:41:17.469 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.469
2025-07-02 06:41:17.469 # do intraline marking on the synch pair
2025-07-02 06:41:17.469 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.469 if eqi is None:
2025-07-02 06:41:17.469 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.469 atags = btags = ""
2025-07-02 06:41:17.469 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.469 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.469 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.469 if tag == 'replace':
2025-07-02 06:41:17.469 atags += '^' * la
2025-07-02 06:41:17.469 btags += '^' * lb
2025-07-02 06:41:17.469 elif tag == 'delete':
2025-07-02 06:41:17.469 atags += '-' * la
2025-07-02 06:41:17.469 elif tag == 'insert':
2025-07-02 06:41:17.469 btags += '+' * lb
2025-07-02 06:41:17.470 elif tag == 'equal':
2025-07-02 06:41:17.470 atags += ' ' * la
2025-07-02 06:41:17.470 btags += ' ' * lb
2025-07-02 06:41:17.470 else:
2025-07-02 06:41:17.470 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.470 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.470 else:
2025-07-02 06:41:17.470 # the synch pair is identical
2025-07-02 06:41:17.470 yield ' ' + aelt
2025-07-02 06:41:17.470
2025-07-02 06:41:17.470 # pump out diffs from after the synch point
2025-07-02 06:41:17.470 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.470
2025-07-02 06:41:17.470 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.470 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.470
2025-07-02 06:41:17.470 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.470 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.470 alo = 235, ahi = 1101
2025-07-02 06:41:17.470 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.471 blo = 235, bhi = 1101
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.471 g = []
2025-07-02 06:41:17.471 if alo < ahi:
2025-07-02 06:41:17.471 if blo < bhi:
2025-07-02 06:41:17.471 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.471 else:
2025-07-02 06:41:17.471 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.471 elif blo < bhi:
2025-07-02 06:41:17.471 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 > yield from g
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.471 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.471 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.472 alo = 235, ahi = 1101
2025-07-02 06:41:17.472 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.472 blo = 235, bhi = 1101
2025-07-02 06:41:17.472
2025-07-02 06:41:17.472 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.472 r"""
2025-07-02 06:41:17.472 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.472 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.472 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.472 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.472
2025-07-02 06:41:17.472 Example:
2025-07-02 06:41:17.472
2025-07-02 06:41:17.472 >>> d = Differ()
2025-07-02 06:41:17.472 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.472 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.472 >>> print(''.join(results), end="")
2025-07-02 06:41:17.472 - abcDefghiJkl
2025-07-02 06:41:17.473 + abcdefGhijkl
2025-07-02 06:41:17.473 """
2025-07-02 06:41:17.473
2025-07-02 06:41:17.473 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.473 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.473 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.473 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.473 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.473
2025-07-02 06:41:17.473 # search for the pair that matches best without being identical
2025-07-02 06:41:17.473 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.473 # on junk -- unless we have to)
2025-07-02 06:41:17.473 for j in range(blo, bhi):
2025-07-02 06:41:17.473 bj = b[j]
2025-07-02 06:41:17.473 cruncher.set_seq2(bj)
2025-07-02 06:41:17.473 for i in range(alo, ahi):
2025-07-02 06:41:17.473 ai = a[i]
2025-07-02 06:41:17.474 if ai == bj:
2025-07-02 06:41:17.474 if eqi is None:
2025-07-02 06:41:17.474 eqi, eqj = i, j
2025-07-02 06:41:17.474 continue
2025-07-02 06:41:17.474 cruncher.set_seq1(ai)
2025-07-02 06:41:17.474 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.474 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.474 # compares by a factor of 3.
2025-07-02 06:41:17.474 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.474 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.474 # of the computation is cached by cruncher
2025-07-02 06:41:17.474 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.474 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.474 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.474 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.474 if best_ratio < cutoff:
2025-07-02 06:41:17.474 # no non-identical "pretty close" pair
2025-07-02 06:41:17.474 if eqi is None:
2025-07-02 06:41:17.475 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.475 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.475 return
2025-07-02 06:41:17.475 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.475 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.475 else:
2025-07-02 06:41:17.475 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.475 eqi = None
2025-07-02 06:41:17.475
2025-07-02 06:41:17.475 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.475 # identical
2025-07-02 06:41:17.475
2025-07-02 06:41:17.475 # pump out diffs from before the synch point
2025-07-02 06:41:17.475 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.475
2025-07-02 06:41:17.475 # do intraline marking on the synch pair
2025-07-02 06:41:17.475 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.475 if eqi is None:
2025-07-02 06:41:17.475 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.476 atags = btags = ""
2025-07-02 06:41:17.476 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.476 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.476 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.476 if tag == 'replace':
2025-07-02 06:41:17.476 atags += '^' * la
2025-07-02 06:41:17.476 btags += '^' * lb
2025-07-02 06:41:17.476 elif tag == 'delete':
2025-07-02 06:41:17.476 atags += '-' * la
2025-07-02 06:41:17.476 elif tag == 'insert':
2025-07-02 06:41:17.476 btags += '+' * lb
2025-07-02 06:41:17.476 elif tag == 'equal':
2025-07-02 06:41:17.476 atags += ' ' * la
2025-07-02 06:41:17.476 btags += ' ' * lb
2025-07-02 06:41:17.476 else:
2025-07-02 06:41:17.476 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.476 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.476 else:
2025-07-02 06:41:17.477 # the synch pair is identical
2025-07-02 06:41:17.477 yield ' ' + aelt
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477 # pump out diffs from after the synch point
2025-07-02 06:41:17.477 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.477 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.477 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.477 alo = 236, ahi = 1101
2025-07-02 06:41:17.477 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.477 blo = 236, bhi = 1101
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.477 g = []
2025-07-02 06:41:17.477 if alo < ahi:
2025-07-02 06:41:17.478 if blo < bhi:
2025-07-02 06:41:17.478 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.478 else:
2025-07-02 06:41:17.478 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.478 elif blo < bhi:
2025-07-02 06:41:17.478 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.478
2025-07-02 06:41:17.478 > yield from g
2025-07-02 06:41:17.478
2025-07-02 06:41:17.478 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.478 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.478
2025-07-02 06:41:17.478 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.478 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.478 alo = 236, ahi = 1101
2025-07-02 06:41:17.478 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.478 blo = 236, bhi = 1101
2025-07-02 06:41:17.478
2025-07-02 06:41:17.479 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.479 r"""
2025-07-02 06:41:17.479 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.479 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.479 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.479 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.479
2025-07-02 06:41:17.479 Example:
2025-07-02 06:41:17.479
2025-07-02 06:41:17.479 >>> d = Differ()
2025-07-02 06:41:17.479 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.479 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.479 >>> print(''.join(results), end="")
2025-07-02 06:41:17.479 - abcDefghiJkl
2025-07-02 06:41:17.479 + abcdefGhijkl
2025-07-02 06:41:17.479 """
2025-07-02 06:41:17.479
2025-07-02 06:41:17.480 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.480 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.480 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.480 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.480 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.480
2025-07-02 06:41:17.480 # search for the pair that matches best without being identical
2025-07-02 06:41:17.480 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.480 # on junk -- unless we have to)
2025-07-02 06:41:17.480 for j in range(blo, bhi):
2025-07-02 06:41:17.480 bj = b[j]
2025-07-02 06:41:17.480 cruncher.set_seq2(bj)
2025-07-02 06:41:17.480 for i in range(alo, ahi):
2025-07-02 06:41:17.480 ai = a[i]
2025-07-02 06:41:17.480 if ai == bj:
2025-07-02 06:41:17.480 if eqi is None:
2025-07-02 06:41:17.480 eqi, eqj = i, j
2025-07-02 06:41:17.480 continue
2025-07-02 06:41:17.480 cruncher.set_seq1(ai)
2025-07-02 06:41:17.481 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.481 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.481 # compares by a factor of 3.
2025-07-02 06:41:17.481 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.481 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.481 # of the computation is cached by cruncher
2025-07-02 06:41:17.481 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.481 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.481 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.481 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.481 if best_ratio < cutoff:
2025-07-02 06:41:17.481 # no non-identical "pretty close" pair
2025-07-02 06:41:17.481 if eqi is None:
2025-07-02 06:41:17.481 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.481 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.481 return
2025-07-02 06:41:17.481 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.481 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.482 else:
2025-07-02 06:41:17.482 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.482 eqi = None
2025-07-02 06:41:17.482
2025-07-02 06:41:17.482 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.482 # identical
2025-07-02 06:41:17.482
2025-07-02 06:41:17.482 # pump out diffs from before the synch point
2025-07-02 06:41:17.482 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.482
2025-07-02 06:41:17.482 # do intraline marking on the synch pair
2025-07-02 06:41:17.482 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.482 if eqi is None:
2025-07-02 06:41:17.482 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.482 atags = btags = ""
2025-07-02 06:41:17.482 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.482 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.482 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.482 if tag == 'replace':
2025-07-02 06:41:17.483 atags += '^' * la
2025-07-02 06:41:17.483 btags += '^' * lb
2025-07-02 06:41:17.483 elif tag == 'delete':
2025-07-02 06:41:17.483 atags += '-' * la
2025-07-02 06:41:17.483 elif tag == 'insert':
2025-07-02 06:41:17.483 btags += '+' * lb
2025-07-02 06:41:17.483 elif tag == 'equal':
2025-07-02 06:41:17.483 atags += ' ' * la
2025-07-02 06:41:17.483 btags += ' ' * lb
2025-07-02 06:41:17.483 else:
2025-07-02 06:41:17.483 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.483 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.483 else:
2025-07-02 06:41:17.483 # the synch pair is identical
2025-07-02 06:41:17.483 yield ' ' + aelt
2025-07-02 06:41:17.483
2025-07-02 06:41:17.483 # pump out diffs from after the synch point
2025-07-02 06:41:17.483 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.483
2025-07-02 06:41:17.483 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.484 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.484
2025-07-02 06:41:17.484 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.484 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.484 alo = 237, ahi = 1101
2025-07-02 06:41:17.484 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.484 blo = 237, bhi = 1101
2025-07-02 06:41:17.484
2025-07-02 06:41:17.484 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.484 g = []
2025-07-02 06:41:17.484 if alo < ahi:
2025-07-02 06:41:17.484 if blo < bhi:
2025-07-02 06:41:17.484 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.484 else:
2025-07-02 06:41:17.484 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.484 elif blo < bhi:
2025-07-02 06:41:17.484 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.484
2025-07-02 06:41:17.485 > yield from g
2025-07-02 06:41:17.485
2025-07-02 06:41:17.485 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.485 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.485
2025-07-02 06:41:17.485 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.485 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.485 alo = 237, ahi = 1101
2025-07-02 06:41:17.485 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.485 blo = 237, bhi = 1101
2025-07-02 06:41:17.485
2025-07-02 06:41:17.485 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.485 r"""
2025-07-02 06:41:17.485 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.485 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.485 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.485 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.486
2025-07-02 06:41:17.486 Example:
2025-07-02 06:41:17.486
2025-07-02 06:41:17.486 >>> d = Differ()
2025-07-02 06:41:17.486 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.486 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.486 >>> print(''.join(results), end="")
2025-07-02 06:41:17.486 - abcDefghiJkl
2025-07-02 06:41:17.486 + abcdefGhijkl
2025-07-02 06:41:17.486 """
2025-07-02 06:41:17.486
2025-07-02 06:41:17.486 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.486 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.486 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.486 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.486 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.486
2025-07-02 06:41:17.487 # search for the pair that matches best without being identical
2025-07-02 06:41:17.487 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.487 # on junk -- unless we have to)
2025-07-02 06:41:17.487 for j in range(blo, bhi):
2025-07-02 06:41:17.487 bj = b[j]
2025-07-02 06:41:17.487 cruncher.set_seq2(bj)
2025-07-02 06:41:17.487 for i in range(alo, ahi):
2025-07-02 06:41:17.487 ai = a[i]
2025-07-02 06:41:17.487 if ai == bj:
2025-07-02 06:41:17.487 if eqi is None:
2025-07-02 06:41:17.487 eqi, eqj = i, j
2025-07-02 06:41:17.487 continue
2025-07-02 06:41:17.487 cruncher.set_seq1(ai)
2025-07-02 06:41:17.487 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.487 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.487 # compares by a factor of 3.
2025-07-02 06:41:17.487 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.487 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.487 # of the computation is cached by cruncher
2025-07-02 06:41:17.488 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.488 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.488 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.488 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.488 if best_ratio < cutoff:
2025-07-02 06:41:17.488 # no non-identical "pretty close" pair
2025-07-02 06:41:17.488 if eqi is None:
2025-07-02 06:41:17.488 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.488 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.488 return
2025-07-02 06:41:17.488 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.488 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.488 else:
2025-07-02 06:41:17.488 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.488 eqi = None
2025-07-02 06:41:17.488
2025-07-02 06:41:17.488 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.488 # identical
2025-07-02 06:41:17.488
2025-07-02 06:41:17.488 # pump out diffs from before the synch point
2025-07-02 06:41:17.489 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.489
2025-07-02 06:41:17.489 # do intraline marking on the synch pair
2025-07-02 06:41:17.489 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.489 if eqi is None:
2025-07-02 06:41:17.489 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.489 atags = btags = ""
2025-07-02 06:41:17.489 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.489 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.489 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.489 if tag == 'replace':
2025-07-02 06:41:17.489 atags += '^' * la
2025-07-02 06:41:17.489 btags += '^' * lb
2025-07-02 06:41:17.489 elif tag == 'delete':
2025-07-02 06:41:17.489 atags += '-' * la
2025-07-02 06:41:17.489 elif tag == 'insert':
2025-07-02 06:41:17.489 btags += '+' * lb
2025-07-02 06:41:17.490 elif tag == 'equal':
2025-07-02 06:41:17.490 atags += ' ' * la
2025-07-02 06:41:17.490 btags += ' ' * lb
2025-07-02 06:41:17.490 else:
2025-07-02 06:41:17.490 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.490 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.490 else:
2025-07-02 06:41:17.490 # the synch pair is identical
2025-07-02 06:41:17.490 yield ' ' + aelt
2025-07-02 06:41:17.490
2025-07-02 06:41:17.490 # pump out diffs from after the synch point
2025-07-02 06:41:17.490 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.490
2025-07-02 06:41:17.490 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.490 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.490
2025-07-02 06:41:17.490 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.490 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.490 alo = 238, ahi = 1101
2025-07-02 06:41:17.491 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.491 blo = 238, bhi = 1101
2025-07-02 06:41:17.491
2025-07-02 06:41:17.491 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.491 g = []
2025-07-02 06:41:17.491 if alo < ahi:
2025-07-02 06:41:17.491 if blo < bhi:
2025-07-02 06:41:17.491 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.491 else:
2025-07-02 06:41:17.491 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.491 elif blo < bhi:
2025-07-02 06:41:17.491 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.491
2025-07-02 06:41:17.491 > yield from g
2025-07-02 06:41:17.491
2025-07-02 06:41:17.491 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.491 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.492 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.492 alo = 238, ahi = 1101
2025-07-02 06:41:17.492 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.492 blo = 238, bhi = 1101
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.492 r"""
2025-07-02 06:41:17.492 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.492 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.492 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.492 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492 Example:
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492 >>> d = Differ()
2025-07-02 06:41:17.492 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.493 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.493 >>> print(''.join(results), end="")
2025-07-02 06:41:17.493 - abcDefghiJkl
2025-07-02 06:41:17.493 + abcdefGhijkl
2025-07-02 06:41:17.493 """
2025-07-02 06:41:17.493
2025-07-02 06:41:17.493 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.493 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.493 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.493 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.493 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.493
2025-07-02 06:41:17.493 # search for the pair that matches best without being identical
2025-07-02 06:41:17.493 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.493 # on junk -- unless we have to)
2025-07-02 06:41:17.493 for j in range(blo, bhi):
2025-07-02 06:41:17.493 bj = b[j]
2025-07-02 06:41:17.494 cruncher.set_seq2(bj)
2025-07-02 06:41:17.494 for i in range(alo, ahi):
2025-07-02 06:41:17.494 ai = a[i]
2025-07-02 06:41:17.494 if ai == bj:
2025-07-02 06:41:17.494 if eqi is None:
2025-07-02 06:41:17.494 eqi, eqj = i, j
2025-07-02 06:41:17.494 continue
2025-07-02 06:41:17.494 cruncher.set_seq1(ai)
2025-07-02 06:41:17.494 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.494 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.494 # compares by a factor of 3.
2025-07-02 06:41:17.494 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.494 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.494 # of the computation is cached by cruncher
2025-07-02 06:41:17.494 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.494 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.494 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.495 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.495 if best_ratio < cutoff:
2025-07-02 06:41:17.495 # no non-identical "pretty close" pair
2025-07-02 06:41:17.495 if eqi is None:
2025-07-02 06:41:17.495 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.495 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.495 return
2025-07-02 06:41:17.495 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.495 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.495 else:
2025-07-02 06:41:17.495 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.495 eqi = None
2025-07-02 06:41:17.495
2025-07-02 06:41:17.495 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.495 # identical
2025-07-02 06:41:17.495
2025-07-02 06:41:17.495 # pump out diffs from before the synch point
2025-07-02 06:41:17.496 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.496
2025-07-02 06:41:17.496 # do intraline marking on the synch pair
2025-07-02 06:41:17.496 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.496 if eqi is None:
2025-07-02 06:41:17.496 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.496 atags = btags = ""
2025-07-02 06:41:17.496 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.496 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.496 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.496 if tag == 'replace':
2025-07-02 06:41:17.496 atags += '^' * la
2025-07-02 06:41:17.496 btags += '^' * lb
2025-07-02 06:41:17.496 elif tag == 'delete':
2025-07-02 06:41:17.496 atags += '-' * la
2025-07-02 06:41:17.496 elif tag == 'insert':
2025-07-02 06:41:17.496 btags += '+' * lb
2025-07-02 06:41:17.496 elif tag == 'equal':
2025-07-02 06:41:17.497 atags += ' ' * la
2025-07-02 06:41:17.497 btags += ' ' * lb
2025-07-02 06:41:17.497 else:
2025-07-02 06:41:17.497 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.497 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.497 else:
2025-07-02 06:41:17.497 # the synch pair is identical
2025-07-02 06:41:17.497 yield ' ' + aelt
2025-07-02 06:41:17.497
2025-07-02 06:41:17.497 # pump out diffs from after the synch point
2025-07-02 06:41:17.497 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.497
2025-07-02 06:41:17.497 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.497 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.497
2025-07-02 06:41:17.497 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.497 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.497 alo = 239, ahi = 1101
2025-07-02 06:41:17.497 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.498 blo = 239, bhi = 1101
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.498 g = []
2025-07-02 06:41:17.498 if alo < ahi:
2025-07-02 06:41:17.498 if blo < bhi:
2025-07-02 06:41:17.498 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.498 else:
2025-07-02 06:41:17.498 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.498 elif blo < bhi:
2025-07-02 06:41:17.498 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 > yield from g
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.498 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.498 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.499 alo = 239, ahi = 1101
2025-07-02 06:41:17.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.499 blo = 239, bhi = 1101
2025-07-02 06:41:17.499
2025-07-02 06:41:17.499 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.499 r"""
2025-07-02 06:41:17.499 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.499 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.499 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.499 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.499
2025-07-02 06:41:17.499 Example:
2025-07-02 06:41:17.499
2025-07-02 06:41:17.499 >>> d = Differ()
2025-07-02 06:41:17.499 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.499 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.499 >>> print(''.join(results), end="")
2025-07-02 06:41:17.499 - abcDefghiJkl
2025-07-02 06:41:17.500 + abcdefGhijkl
2025-07-02 06:41:17.500 """
2025-07-02 06:41:17.500
2025-07-02 06:41:17.500 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.500 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.500 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.500 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.500 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.500
2025-07-02 06:41:17.500 # search for the pair that matches best without being identical
2025-07-02 06:41:17.500 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.500 # on junk -- unless we have to)
2025-07-02 06:41:17.500 for j in range(blo, bhi):
2025-07-02 06:41:17.500 bj = b[j]
2025-07-02 06:41:17.500 cruncher.set_seq2(bj)
2025-07-02 06:41:17.500 for i in range(alo, ahi):
2025-07-02 06:41:17.500 ai = a[i]
2025-07-02 06:41:17.500 if ai == bj:
2025-07-02 06:41:17.500 if eqi is None:
2025-07-02 06:41:17.501 eqi, eqj = i, j
2025-07-02 06:41:17.501 continue
2025-07-02 06:41:17.501 cruncher.set_seq1(ai)
2025-07-02 06:41:17.501 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.501 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.501 # compares by a factor of 3.
2025-07-02 06:41:17.501 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.501 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.501 # of the computation is cached by cruncher
2025-07-02 06:41:17.501 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.501 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.501 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.501 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.501 if best_ratio < cutoff:
2025-07-02 06:41:17.501 # no non-identical "pretty close" pair
2025-07-02 06:41:17.501 if eqi is None:
2025-07-02 06:41:17.501 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.501 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.501 return
2025-07-02 06:41:17.501 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.502 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.502 else:
2025-07-02 06:41:17.502 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.502 eqi = None
2025-07-02 06:41:17.502
2025-07-02 06:41:17.502 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.502 # identical
2025-07-02 06:41:17.502
2025-07-02 06:41:17.502 # pump out diffs from before the synch point
2025-07-02 06:41:17.502 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.502
2025-07-02 06:41:17.502 # do intraline marking on the synch pair
2025-07-02 06:41:17.502 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.502 if eqi is None:
2025-07-02 06:41:17.502 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.502 atags = btags = ""
2025-07-02 06:41:17.502 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.502 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.502 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.503 if tag == 'replace':
2025-07-02 06:41:17.503 atags += '^' * la
2025-07-02 06:41:17.503 btags += '^' * lb
2025-07-02 06:41:17.503 elif tag == 'delete':
2025-07-02 06:41:17.503 atags += '-' * la
2025-07-02 06:41:17.503 elif tag == 'insert':
2025-07-02 06:41:17.503 btags += '+' * lb
2025-07-02 06:41:17.503 elif tag == 'equal':
2025-07-02 06:41:17.503 atags += ' ' * la
2025-07-02 06:41:17.503 btags += ' ' * lb
2025-07-02 06:41:17.503 else:
2025-07-02 06:41:17.503 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.503 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.503 else:
2025-07-02 06:41:17.503 # the synch pair is identical
2025-07-02 06:41:17.503 yield ' ' + aelt
2025-07-02 06:41:17.503
2025-07-02 06:41:17.503 # pump out diffs from after the synch point
2025-07-02 06:41:17.503 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.503
2025-07-02 06:41:17.504 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.504 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.504
2025-07-02 06:41:17.504 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.504 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.504 alo = 240, ahi = 1101
2025-07-02 06:41:17.504 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.504 blo = 240, bhi = 1101
2025-07-02 06:41:17.504
2025-07-02 06:41:17.504 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.504 g = []
2025-07-02 06:41:17.504 if alo < ahi:
2025-07-02 06:41:17.504 if blo < bhi:
2025-07-02 06:41:17.504 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.504 else:
2025-07-02 06:41:17.504 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.504 elif blo < bhi:
2025-07-02 06:41:17.504 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 > yield from g
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.505 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.505 alo = 240, ahi = 1101
2025-07-02 06:41:17.505 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.505 blo = 240, bhi = 1101
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.505 r"""
2025-07-02 06:41:17.505 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.505 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.505 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.506 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.506
2025-07-02 06:41:17.506 Example:
2025-07-02 06:41:17.506
2025-07-02 06:41:17.506 >>> d = Differ()
2025-07-02 06:41:17.506 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.506 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.506 >>> print(''.join(results), end="")
2025-07-02 06:41:17.506 - abcDefghiJkl
2025-07-02 06:41:17.506 + abcdefGhijkl
2025-07-02 06:41:17.506 """
2025-07-02 06:41:17.506
2025-07-02 06:41:17.506 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.506 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.506 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.506 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.506 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.507
2025-07-02 06:41:17.507 # search for the pair that matches best without being identical
2025-07-02 06:41:17.507 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.507 # on junk -- unless we have to)
2025-07-02 06:41:17.507 for j in range(blo, bhi):
2025-07-02 06:41:17.507 bj = b[j]
2025-07-02 06:41:17.507 cruncher.set_seq2(bj)
2025-07-02 06:41:17.507 for i in range(alo, ahi):
2025-07-02 06:41:17.507 ai = a[i]
2025-07-02 06:41:17.507 if ai == bj:
2025-07-02 06:41:17.507 if eqi is None:
2025-07-02 06:41:17.507 eqi, eqj = i, j
2025-07-02 06:41:17.507 continue
2025-07-02 06:41:17.507 cruncher.set_seq1(ai)
2025-07-02 06:41:17.507 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.507 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.507 # compares by a factor of 3.
2025-07-02 06:41:17.507 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.507 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.508 # of the computation is cached by cruncher
2025-07-02 06:41:17.508 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.508 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.508 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.508 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.508 if best_ratio < cutoff:
2025-07-02 06:41:17.508 # no non-identical "pretty close" pair
2025-07-02 06:41:17.508 if eqi is None:
2025-07-02 06:41:17.508 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.508 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.508 return
2025-07-02 06:41:17.508 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.508 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.508 else:
2025-07-02 06:41:17.508 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.508 eqi = None
2025-07-02 06:41:17.508
2025-07-02 06:41:17.508 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.509 # identical
2025-07-02 06:41:17.509
2025-07-02 06:41:17.509 # pump out diffs from before the synch point
2025-07-02 06:41:17.509 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.509
2025-07-02 06:41:17.509 # do intraline marking on the synch pair
2025-07-02 06:41:17.509 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.509 if eqi is None:
2025-07-02 06:41:17.509 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.509 atags = btags = ""
2025-07-02 06:41:17.509 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.509 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.509 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.509 if tag == 'replace':
2025-07-02 06:41:17.509 atags += '^' * la
2025-07-02 06:41:17.509 btags += '^' * lb
2025-07-02 06:41:17.509 elif tag == 'delete':
2025-07-02 06:41:17.509 atags += '-' * la
2025-07-02 06:41:17.509 elif tag == 'insert':
2025-07-02 06:41:17.510 btags += '+' * lb
2025-07-02 06:41:17.510 elif tag == 'equal':
2025-07-02 06:41:17.510 atags += ' ' * la
2025-07-02 06:41:17.510 btags += ' ' * lb
2025-07-02 06:41:17.510 else:
2025-07-02 06:41:17.510 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.510 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.510 else:
2025-07-02 06:41:17.510 # the synch pair is identical
2025-07-02 06:41:17.510 yield ' ' + aelt
2025-07-02 06:41:17.510
2025-07-02 06:41:17.510 # pump out diffs from after the synch point
2025-07-02 06:41:17.510 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.510
2025-07-02 06:41:17.510 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.510 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.510
2025-07-02 06:41:17.510 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.510 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.511 alo = 241, ahi = 1101
2025-07-02 06:41:17.511 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.511 blo = 241, bhi = 1101
2025-07-02 06:41:17.511
2025-07-02 06:41:17.511 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.511 g = []
2025-07-02 06:41:17.511 if alo < ahi:
2025-07-02 06:41:17.511 if blo < bhi:
2025-07-02 06:41:17.511 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.511 else:
2025-07-02 06:41:17.511 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.511 elif blo < bhi:
2025-07-02 06:41:17.511 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.511
2025-07-02 06:41:17.511 > yield from g
2025-07-02 06:41:17.511
2025-07-02 06:41:17.511 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.511
2025-07-02 06:41:17.512 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.512 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.512 alo = 241, ahi = 1101
2025-07-02 06:41:17.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.512 blo = 241, bhi = 1101
2025-07-02 06:41:17.512
2025-07-02 06:41:17.512 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.512 r"""
2025-07-02 06:41:17.512 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.512 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.512 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.512 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.512
2025-07-02 06:41:17.512 Example:
2025-07-02 06:41:17.512
2025-07-02 06:41:17.512 >>> d = Differ()
2025-07-02 06:41:17.512 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.512 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.513 >>> print(''.join(results), end="")
2025-07-02 06:41:17.513 - abcDefghiJkl
2025-07-02 06:41:17.513 + abcdefGhijkl
2025-07-02 06:41:17.513 """
2025-07-02 06:41:17.513
2025-07-02 06:41:17.513 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.513 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.513 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.513 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.513 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.513
2025-07-02 06:41:17.513 # search for the pair that matches best without being identical
2025-07-02 06:41:17.513 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.513 # on junk -- unless we have to)
2025-07-02 06:41:17.513 for j in range(blo, bhi):
2025-07-02 06:41:17.514 bj = b[j]
2025-07-02 06:41:17.514 cruncher.set_seq2(bj)
2025-07-02 06:41:17.514 for i in range(alo, ahi):
2025-07-02 06:41:17.514 ai = a[i]
2025-07-02 06:41:17.514 if ai == bj:
2025-07-02 06:41:17.514 if eqi is None:
2025-07-02 06:41:17.514 eqi, eqj = i, j
2025-07-02 06:41:17.514 continue
2025-07-02 06:41:17.514 cruncher.set_seq1(ai)
2025-07-02 06:41:17.514 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.514 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.514 # compares by a factor of 3.
2025-07-02 06:41:17.514 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.514 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.514 # of the computation is cached by cruncher
2025-07-02 06:41:17.514 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.514 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.514 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.514 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.515 if best_ratio < cutoff:
2025-07-02 06:41:17.515 # no non-identical "pretty close" pair
2025-07-02 06:41:17.515 if eqi is None:
2025-07-02 06:41:17.515 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.515 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.515 return
2025-07-02 06:41:17.515 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.515 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.515 else:
2025-07-02 06:41:17.515 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.515 eqi = None
2025-07-02 06:41:17.515
2025-07-02 06:41:17.515 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.515 # identical
2025-07-02 06:41:17.515
2025-07-02 06:41:17.515 # pump out diffs from before the synch point
2025-07-02 06:41:17.515 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.515
2025-07-02 06:41:17.516 # do intraline marking on the synch pair
2025-07-02 06:41:17.516 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.516 if eqi is None:
2025-07-02 06:41:17.516 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.516 atags = btags = ""
2025-07-02 06:41:17.516 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.516 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.516 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.516 if tag == 'replace':
2025-07-02 06:41:17.516 atags += '^' * la
2025-07-02 06:41:17.516 btags += '^' * lb
2025-07-02 06:41:17.516 elif tag == 'delete':
2025-07-02 06:41:17.516 atags += '-' * la
2025-07-02 06:41:17.516 elif tag == 'insert':
2025-07-02 06:41:17.516 btags += '+' * lb
2025-07-02 06:41:17.516 elif tag == 'equal':
2025-07-02 06:41:17.516 atags += ' ' * la
2025-07-02 06:41:17.516 btags += ' ' * lb
2025-07-02 06:41:17.516 else:
2025-07-02 06:41:17.516 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.517 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.517 else:
2025-07-02 06:41:17.517 # the synch pair is identical
2025-07-02 06:41:17.517 yield ' ' + aelt
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517 # pump out diffs from after the synch point
2025-07-02 06:41:17.517 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.517 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.517 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.517 alo = 242, ahi = 1101
2025-07-02 06:41:17.517 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.517 blo = 242, bhi = 1101
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.517 g = []
2025-07-02 06:41:17.518 if alo < ahi:
2025-07-02 06:41:17.518 if blo < bhi:
2025-07-02 06:41:17.518 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.518 else:
2025-07-02 06:41:17.518 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.518 elif blo < bhi:
2025-07-02 06:41:17.518 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.518
2025-07-02 06:41:17.518 > yield from g
2025-07-02 06:41:17.518
2025-07-02 06:41:17.518 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.518 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.518
2025-07-02 06:41:17.518 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.518 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.518 alo = 242, ahi = 1101
2025-07-02 06:41:17.518 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.518 blo = 242, bhi = 1101
2025-07-02 06:41:17.518
2025-07-02 06:41:17.519 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.519 r"""
2025-07-02 06:41:17.519 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.519 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.519 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.519 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.519
2025-07-02 06:41:17.519 Example:
2025-07-02 06:41:17.519
2025-07-02 06:41:17.519 >>> d = Differ()
2025-07-02 06:41:17.519 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.519 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.519 >>> print(''.join(results), end="")
2025-07-02 06:41:17.519 - abcDefghiJkl
2025-07-02 06:41:17.519 + abcdefGhijkl
2025-07-02 06:41:17.519 """
2025-07-02 06:41:17.519
2025-07-02 06:41:17.519 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.520 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.520 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.520 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.520 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.520
2025-07-02 06:41:17.520 # search for the pair that matches best without being identical
2025-07-02 06:41:17.520 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.520 # on junk -- unless we have to)
2025-07-02 06:41:17.520 for j in range(blo, bhi):
2025-07-02 06:41:17.520 bj = b[j]
2025-07-02 06:41:17.520 cruncher.set_seq2(bj)
2025-07-02 06:41:17.520 for i in range(alo, ahi):
2025-07-02 06:41:17.520 ai = a[i]
2025-07-02 06:41:17.520 if ai == bj:
2025-07-02 06:41:17.520 if eqi is None:
2025-07-02 06:41:17.520 eqi, eqj = i, j
2025-07-02 06:41:17.520 continue
2025-07-02 06:41:17.520 cruncher.set_seq1(ai)
2025-07-02 06:41:17.520 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.520 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.521 # compares by a factor of 3.
2025-07-02 06:41:17.521 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.521 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.521 # of the computation is cached by cruncher
2025-07-02 06:41:17.521 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.521 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.521 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.521 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.521 if best_ratio < cutoff:
2025-07-02 06:41:17.521 # no non-identical "pretty close" pair
2025-07-02 06:41:17.521 if eqi is None:
2025-07-02 06:41:17.521 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.521 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.521 return
2025-07-02 06:41:17.521 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.521 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.521 else:
2025-07-02 06:41:17.521 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.522 eqi = None
2025-07-02 06:41:17.522
2025-07-02 06:41:17.522 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.522 # identical
2025-07-02 06:41:17.522
2025-07-02 06:41:17.522 # pump out diffs from before the synch point
2025-07-02 06:41:17.522 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.522
2025-07-02 06:41:17.522 # do intraline marking on the synch pair
2025-07-02 06:41:17.522 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.522 if eqi is None:
2025-07-02 06:41:17.522 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.522 atags = btags = ""
2025-07-02 06:41:17.522 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.522 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.522 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.522 if tag == 'replace':
2025-07-02 06:41:17.523 atags += '^' * la
2025-07-02 06:41:17.523 btags += '^' * lb
2025-07-02 06:41:17.523 elif tag == 'delete':
2025-07-02 06:41:17.523 atags += '-' * la
2025-07-02 06:41:17.523 elif tag == 'insert':
2025-07-02 06:41:17.523 btags += '+' * lb
2025-07-02 06:41:17.523 elif tag == 'equal':
2025-07-02 06:41:17.523 atags += ' ' * la
2025-07-02 06:41:17.523 btags += ' ' * lb
2025-07-02 06:41:17.523 else:
2025-07-02 06:41:17.523 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.523 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.523 else:
2025-07-02 06:41:17.523 # the synch pair is identical
2025-07-02 06:41:17.523 yield ' ' + aelt
2025-07-02 06:41:17.523
2025-07-02 06:41:17.523 # pump out diffs from after the synch point
2025-07-02 06:41:17.523 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.523
2025-07-02 06:41:17.524 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.524 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.524
2025-07-02 06:41:17.524 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.524 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.524 alo = 243, ahi = 1101
2025-07-02 06:41:17.524 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.524 blo = 243, bhi = 1101
2025-07-02 06:41:17.524
2025-07-02 06:41:17.524 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.524 g = []
2025-07-02 06:41:17.524 if alo < ahi:
2025-07-02 06:41:17.524 if blo < bhi:
2025-07-02 06:41:17.524 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.524 else:
2025-07-02 06:41:17.524 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.524 elif blo < bhi:
2025-07-02 06:41:17.524 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.524
2025-07-02 06:41:17.525 > yield from g
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.525 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.525 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.525 alo = 243, ahi = 1101
2025-07-02 06:41:17.525 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.525 blo = 243, bhi = 1101
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.525 r"""
2025-07-02 06:41:17.525 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.525 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.525 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.525 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525 Example:
2025-07-02 06:41:17.526
2025-07-02 06:41:17.526 >>> d = Differ()
2025-07-02 06:41:17.526 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.526 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.526 >>> print(''.join(results), end="")
2025-07-02 06:41:17.526 - abcDefghiJkl
2025-07-02 06:41:17.526 + abcdefGhijkl
2025-07-02 06:41:17.526 """
2025-07-02 06:41:17.526
2025-07-02 06:41:17.526 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.526 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.526 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.526 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.526 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.526
2025-07-02 06:41:17.526 # search for the pair that matches best without being identical
2025-07-02 06:41:17.526 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.526 # on junk -- unless we have to)
2025-07-02 06:41:17.527 for j in range(blo, bhi):
2025-07-02 06:41:17.527 bj = b[j]
2025-07-02 06:41:17.527 cruncher.set_seq2(bj)
2025-07-02 06:41:17.527 for i in range(alo, ahi):
2025-07-02 06:41:17.527 ai = a[i]
2025-07-02 06:41:17.527 if ai == bj:
2025-07-02 06:41:17.527 if eqi is None:
2025-07-02 06:41:17.527 eqi, eqj = i, j
2025-07-02 06:41:17.527 continue
2025-07-02 06:41:17.527 cruncher.set_seq1(ai)
2025-07-02 06:41:17.527 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.527 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.527 # compares by a factor of 3.
2025-07-02 06:41:17.527 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.527 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.527 # of the computation is cached by cruncher
2025-07-02 06:41:17.527 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.527 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.527 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.528 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.528 if best_ratio < cutoff:
2025-07-02 06:41:17.528 # no non-identical "pretty close" pair
2025-07-02 06:41:17.528 if eqi is None:
2025-07-02 06:41:17.528 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.528 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.528 return
2025-07-02 06:41:17.528 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.528 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.528 else:
2025-07-02 06:41:17.528 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.528 eqi = None
2025-07-02 06:41:17.528
2025-07-02 06:41:17.528 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.528 # identical
2025-07-02 06:41:17.528
2025-07-02 06:41:17.528 # pump out diffs from before the synch point
2025-07-02 06:41:17.528 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.528
2025-07-02 06:41:17.528 # do intraline marking on the synch pair
2025-07-02 06:41:17.529 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.529 if eqi is None:
2025-07-02 06:41:17.529 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.529 atags = btags = ""
2025-07-02 06:41:17.529 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.529 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.529 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.529 if tag == 'replace':
2025-07-02 06:41:17.529 atags += '^' * la
2025-07-02 06:41:17.529 btags += '^' * lb
2025-07-02 06:41:17.529 elif tag == 'delete':
2025-07-02 06:41:17.529 atags += '-' * la
2025-07-02 06:41:17.529 elif tag == 'insert':
2025-07-02 06:41:17.529 btags += '+' * lb
2025-07-02 06:41:17.529 elif tag == 'equal':
2025-07-02 06:41:17.529 atags += ' ' * la
2025-07-02 06:41:17.529 btags += ' ' * lb
2025-07-02 06:41:17.529 else:
2025-07-02 06:41:17.529 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.530 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.530 else:
2025-07-02 06:41:17.530 # the synch pair is identical
2025-07-02 06:41:17.530 yield ' ' + aelt
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530 # pump out diffs from after the synch point
2025-07-02 06:41:17.530 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.530 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.530 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.530 alo = 246, ahi = 1101
2025-07-02 06:41:17.530 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.530 blo = 246, bhi = 1101
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.530 g = []
2025-07-02 06:41:17.530 if alo < ahi:
2025-07-02 06:41:17.531 if blo < bhi:
2025-07-02 06:41:17.531 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.531 else:
2025-07-02 06:41:17.531 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.531 elif blo < bhi:
2025-07-02 06:41:17.531 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.531
2025-07-02 06:41:17.531 > yield from g
2025-07-02 06:41:17.531
2025-07-02 06:41:17.531 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.531 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.531
2025-07-02 06:41:17.531 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.531 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.531 alo = 246, ahi = 1101
2025-07-02 06:41:17.531 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.531 blo = 246, bhi = 1101
2025-07-02 06:41:17.531
2025-07-02 06:41:17.532 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.532 r"""
2025-07-02 06:41:17.532 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.532 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.532 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.532 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.532
2025-07-02 06:41:17.532 Example:
2025-07-02 06:41:17.532
2025-07-02 06:41:17.532 >>> d = Differ()
2025-07-02 06:41:17.532 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.532 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.532 >>> print(''.join(results), end="")
2025-07-02 06:41:17.532 - abcDefghiJkl
2025-07-02 06:41:17.532 + abcdefGhijkl
2025-07-02 06:41:17.532 """
2025-07-02 06:41:17.532
2025-07-02 06:41:17.533 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.533 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.533 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.533 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.533 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.533
2025-07-02 06:41:17.533 # search for the pair that matches best without being identical
2025-07-02 06:41:17.533 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.533 # on junk -- unless we have to)
2025-07-02 06:41:17.533 for j in range(blo, bhi):
2025-07-02 06:41:17.533 bj = b[j]
2025-07-02 06:41:17.533 cruncher.set_seq2(bj)
2025-07-02 06:41:17.533 for i in range(alo, ahi):
2025-07-02 06:41:17.533 ai = a[i]
2025-07-02 06:41:17.533 if ai == bj:
2025-07-02 06:41:17.533 if eqi is None:
2025-07-02 06:41:17.533 eqi, eqj = i, j
2025-07-02 06:41:17.533 continue
2025-07-02 06:41:17.533 cruncher.set_seq1(ai)
2025-07-02 06:41:17.534 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.534 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.534 # compares by a factor of 3.
2025-07-02 06:41:17.534 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.534 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.534 # of the computation is cached by cruncher
2025-07-02 06:41:17.534 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.534 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.534 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.534 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.534 if best_ratio < cutoff:
2025-07-02 06:41:17.534 # no non-identical "pretty close" pair
2025-07-02 06:41:17.534 if eqi is None:
2025-07-02 06:41:17.534 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.534 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.534 return
2025-07-02 06:41:17.534 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.534 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.534 else:
2025-07-02 06:41:17.534 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.535 eqi = None
2025-07-02 06:41:17.535
2025-07-02 06:41:17.535 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.535 # identical
2025-07-02 06:41:17.535
2025-07-02 06:41:17.535 # pump out diffs from before the synch point
2025-07-02 06:41:17.535 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.535
2025-07-02 06:41:17.535 # do intraline marking on the synch pair
2025-07-02 06:41:17.535 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.535 if eqi is None:
2025-07-02 06:41:17.535 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.535 atags = btags = ""
2025-07-02 06:41:17.535 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.535 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.535 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.535 if tag == 'replace':
2025-07-02 06:41:17.535 atags += '^' * la
2025-07-02 06:41:17.536 btags += '^' * lb
2025-07-02 06:41:17.536 elif tag == 'delete':
2025-07-02 06:41:17.536 atags += '-' * la
2025-07-02 06:41:17.536 elif tag == 'insert':
2025-07-02 06:41:17.536 btags += '+' * lb
2025-07-02 06:41:17.536 elif tag == 'equal':
2025-07-02 06:41:17.536 atags += ' ' * la
2025-07-02 06:41:17.536 btags += ' ' * lb
2025-07-02 06:41:17.536 else:
2025-07-02 06:41:17.536 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.536 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.536 else:
2025-07-02 06:41:17.536 # the synch pair is identical
2025-07-02 06:41:17.536 yield ' ' + aelt
2025-07-02 06:41:17.536
2025-07-02 06:41:17.536 # pump out diffs from after the synch point
2025-07-02 06:41:17.536 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.536
2025-07-02 06:41:17.537 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.537 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.537
2025-07-02 06:41:17.537 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.537 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.537 alo = 247, ahi = 1101
2025-07-02 06:41:17.537 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.537 blo = 247, bhi = 1101
2025-07-02 06:41:17.537
2025-07-02 06:41:17.537 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.537 g = []
2025-07-02 06:41:17.537 if alo < ahi:
2025-07-02 06:41:17.537 if blo < bhi:
2025-07-02 06:41:17.537 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.537 else:
2025-07-02 06:41:17.537 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.537 elif blo < bhi:
2025-07-02 06:41:17.538 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 > yield from g
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.538 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.538 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.538 alo = 247, ahi = 1101
2025-07-02 06:41:17.538 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.538 blo = 247, bhi = 1101
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.538 r"""
2025-07-02 06:41:17.538 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.538 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.538 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.538 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539 Example:
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539 >>> d = Differ()
2025-07-02 06:41:17.539 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.539 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.539 >>> print(''.join(results), end="")
2025-07-02 06:41:17.539 - abcDefghiJkl
2025-07-02 06:41:17.539 + abcdefGhijkl
2025-07-02 06:41:17.539 """
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.539 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.539 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.539 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.539 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539 # search for the pair that matches best without being identical
2025-07-02 06:41:17.540 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.540 # on junk -- unless we have to)
2025-07-02 06:41:17.540 for j in range(blo, bhi):
2025-07-02 06:41:17.540 bj = b[j]
2025-07-02 06:41:17.540 cruncher.set_seq2(bj)
2025-07-02 06:41:17.540 for i in range(alo, ahi):
2025-07-02 06:41:17.540 ai = a[i]
2025-07-02 06:41:17.540 if ai == bj:
2025-07-02 06:41:17.540 if eqi is None:
2025-07-02 06:41:17.540 eqi, eqj = i, j
2025-07-02 06:41:17.540 continue
2025-07-02 06:41:17.540 cruncher.set_seq1(ai)
2025-07-02 06:41:17.540 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.540 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.540 # compares by a factor of 3.
2025-07-02 06:41:17.540 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.540 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.540 # of the computation is cached by cruncher
2025-07-02 06:41:17.540 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.541 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.541 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.541 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.541 if best_ratio < cutoff:
2025-07-02 06:41:17.541 # no non-identical "pretty close" pair
2025-07-02 06:41:17.541 if eqi is None:
2025-07-02 06:41:17.541 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.541 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.541 return
2025-07-02 06:41:17.541 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.541 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.541 else:
2025-07-02 06:41:17.541 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.541 eqi = None
2025-07-02 06:41:17.541
2025-07-02 06:41:17.541 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.541 # identical
2025-07-02 06:41:17.541
2025-07-02 06:41:17.542 # pump out diffs from before the synch point
2025-07-02 06:41:17.542 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.542
2025-07-02 06:41:17.542 # do intraline marking on the synch pair
2025-07-02 06:41:17.542 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.542 if eqi is None:
2025-07-02 06:41:17.542 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.542 atags = btags = ""
2025-07-02 06:41:17.542 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.542 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.542 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.542 if tag == 'replace':
2025-07-02 06:41:17.542 atags += '^' * la
2025-07-02 06:41:17.542 btags += '^' * lb
2025-07-02 06:41:17.542 elif tag == 'delete':
2025-07-02 06:41:17.542 atags += '-' * la
2025-07-02 06:41:17.542 elif tag == 'insert':
2025-07-02 06:41:17.542 btags += '+' * lb
2025-07-02 06:41:17.542 elif tag == 'equal':
2025-07-02 06:41:17.543 atags += ' ' * la
2025-07-02 06:41:17.543 btags += ' ' * lb
2025-07-02 06:41:17.543 else:
2025-07-02 06:41:17.543 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.543 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.543 else:
2025-07-02 06:41:17.543 # the synch pair is identical
2025-07-02 06:41:17.543 yield ' ' + aelt
2025-07-02 06:41:17.543
2025-07-02 06:41:17.543 # pump out diffs from after the synch point
2025-07-02 06:41:17.543 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.543
2025-07-02 06:41:17.543 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.543 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.543
2025-07-02 06:41:17.543 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.543 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.543 alo = 248, ahi = 1101
2025-07-02 06:41:17.543 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.544 blo = 248, bhi = 1101
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.544 g = []
2025-07-02 06:41:17.544 if alo < ahi:
2025-07-02 06:41:17.544 if blo < bhi:
2025-07-02 06:41:17.544 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.544 else:
2025-07-02 06:41:17.544 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.544 elif blo < bhi:
2025-07-02 06:41:17.544 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 > yield from g
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.544 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.544 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.544 alo = 248, ahi = 1101
2025-07-02 06:41:17.545 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.545 blo = 248, bhi = 1101
2025-07-02 06:41:17.545
2025-07-02 06:41:17.545 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.545 r"""
2025-07-02 06:41:17.545 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.545 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.545 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.545 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.545
2025-07-02 06:41:17.545 Example:
2025-07-02 06:41:17.545
2025-07-02 06:41:17.545 >>> d = Differ()
2025-07-02 06:41:17.545 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.545 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.545 >>> print(''.join(results), end="")
2025-07-02 06:41:17.545 - abcDefghiJkl
2025-07-02 06:41:17.545 + abcdefGhijkl
2025-07-02 06:41:17.546 """
2025-07-02 06:41:17.546
2025-07-02 06:41:17.546 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.546 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.546 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.546 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.546 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.546
2025-07-02 06:41:17.546 # search for the pair that matches best without being identical
2025-07-02 06:41:17.546 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.546 # on junk -- unless we have to)
2025-07-02 06:41:17.546 for j in range(blo, bhi):
2025-07-02 06:41:17.546 bj = b[j]
2025-07-02 06:41:17.546 cruncher.set_seq2(bj)
2025-07-02 06:41:17.546 for i in range(alo, ahi):
2025-07-02 06:41:17.546 ai = a[i]
2025-07-02 06:41:17.546 if ai == bj:
2025-07-02 06:41:17.546 if eqi is None:
2025-07-02 06:41:17.546 eqi, eqj = i, j
2025-07-02 06:41:17.547 continue
2025-07-02 06:41:17.547 cruncher.set_seq1(ai)
2025-07-02 06:41:17.547 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.547 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.547 # compares by a factor of 3.
2025-07-02 06:41:17.547 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.547 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.547 # of the computation is cached by cruncher
2025-07-02 06:41:17.547 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.547 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.547 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.547 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.547 if best_ratio < cutoff:
2025-07-02 06:41:17.547 # no non-identical "pretty close" pair
2025-07-02 06:41:17.547 if eqi is None:
2025-07-02 06:41:17.547 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.547 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.547 return
2025-07-02 06:41:17.547 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.547 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.548 else:
2025-07-02 06:41:17.548 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.548 eqi = None
2025-07-02 06:41:17.548
2025-07-02 06:41:17.548 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.548 # identical
2025-07-02 06:41:17.548
2025-07-02 06:41:17.548 # pump out diffs from before the synch point
2025-07-02 06:41:17.548 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.548
2025-07-02 06:41:17.548 # do intraline marking on the synch pair
2025-07-02 06:41:17.548 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.548 if eqi is None:
2025-07-02 06:41:17.548 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.548 atags = btags = ""
2025-07-02 06:41:17.548 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.548 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.548 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.548 if tag == 'replace':
2025-07-02 06:41:17.549 atags += '^' * la
2025-07-02 06:41:17.549 btags += '^' * lb
2025-07-02 06:41:17.549 elif tag == 'delete':
2025-07-02 06:41:17.549 atags += '-' * la
2025-07-02 06:41:17.549 elif tag == 'insert':
2025-07-02 06:41:17.549 btags += '+' * lb
2025-07-02 06:41:17.549 elif tag == 'equal':
2025-07-02 06:41:17.549 atags += ' ' * la
2025-07-02 06:41:17.549 btags += ' ' * lb
2025-07-02 06:41:17.549 else:
2025-07-02 06:41:17.549 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.549 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.549 else:
2025-07-02 06:41:17.549 # the synch pair is identical
2025-07-02 06:41:17.549 yield ' ' + aelt
2025-07-02 06:41:17.549
2025-07-02 06:41:17.549 # pump out diffs from after the synch point
2025-07-02 06:41:17.549 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.549
2025-07-02 06:41:17.550 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.550 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.550
2025-07-02 06:41:17.550 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.550 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.550 alo = 249, ahi = 1101
2025-07-02 06:41:17.550 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.550 blo = 249, bhi = 1101
2025-07-02 06:41:17.550
2025-07-02 06:41:17.550 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.550 g = []
2025-07-02 06:41:17.550 if alo < ahi:
2025-07-02 06:41:17.550 if blo < bhi:
2025-07-02 06:41:17.550 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.550 else:
2025-07-02 06:41:17.550 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.550 elif blo < bhi:
2025-07-02 06:41:17.550 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.550
2025-07-02 06:41:17.551 > yield from g
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.551 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.551 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.551 alo = 249, ahi = 1101
2025-07-02 06:41:17.551 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.551 blo = 249, bhi = 1101
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.551 r"""
2025-07-02 06:41:17.551 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.551 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.551 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.551 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551 Example:
2025-07-02 06:41:17.552
2025-07-02 06:41:17.552 >>> d = Differ()
2025-07-02 06:41:17.552 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.552 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.552 >>> print(''.join(results), end="")
2025-07-02 06:41:17.552 - abcDefghiJkl
2025-07-02 06:41:17.552 + abcdefGhijkl
2025-07-02 06:41:17.552 """
2025-07-02 06:41:17.552
2025-07-02 06:41:17.552 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.552 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.552 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.552 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.552 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.552
2025-07-02 06:41:17.552 # search for the pair that matches best without being identical
2025-07-02 06:41:17.552 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.553 # on junk -- unless we have to)
2025-07-02 06:41:17.553 for j in range(blo, bhi):
2025-07-02 06:41:17.553 bj = b[j]
2025-07-02 06:41:17.553 cruncher.set_seq2(bj)
2025-07-02 06:41:17.553 for i in range(alo, ahi):
2025-07-02 06:41:17.553 ai = a[i]
2025-07-02 06:41:17.553 if ai == bj:
2025-07-02 06:41:17.553 if eqi is None:
2025-07-02 06:41:17.553 eqi, eqj = i, j
2025-07-02 06:41:17.553 continue
2025-07-02 06:41:17.553 cruncher.set_seq1(ai)
2025-07-02 06:41:17.553 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.553 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.553 # compares by a factor of 3.
2025-07-02 06:41:17.553 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.553 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.553 # of the computation is cached by cruncher
2025-07-02 06:41:17.553 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.554 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.554 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.554 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.554 if best_ratio < cutoff:
2025-07-02 06:41:17.554 # no non-identical "pretty close" pair
2025-07-02 06:41:17.554 if eqi is None:
2025-07-02 06:41:17.554 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.554 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.554 return
2025-07-02 06:41:17.554 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.554 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.554 else:
2025-07-02 06:41:17.554 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.554 eqi = None
2025-07-02 06:41:17.554
2025-07-02 06:41:17.554 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.554 # identical
2025-07-02 06:41:17.554
2025-07-02 06:41:17.555 # pump out diffs from before the synch point
2025-07-02 06:41:17.555 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.555
2025-07-02 06:41:17.555 # do intraline marking on the synch pair
2025-07-02 06:41:17.555 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.555 if eqi is None:
2025-07-02 06:41:17.555 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.555 atags = btags = ""
2025-07-02 06:41:17.555 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.555 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.555 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.555 if tag == 'replace':
2025-07-02 06:41:17.555 atags += '^' * la
2025-07-02 06:41:17.555 btags += '^' * lb
2025-07-02 06:41:17.555 elif tag == 'delete':
2025-07-02 06:41:17.555 atags += '-' * la
2025-07-02 06:41:17.555 elif tag == 'insert':
2025-07-02 06:41:17.555 btags += '+' * lb
2025-07-02 06:41:17.555 elif tag == 'equal':
2025-07-02 06:41:17.555 atags += ' ' * la
2025-07-02 06:41:17.556 btags += ' ' * lb
2025-07-02 06:41:17.556 else:
2025-07-02 06:41:17.556 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.556 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.556 else:
2025-07-02 06:41:17.556 # the synch pair is identical
2025-07-02 06:41:17.556 yield ' ' + aelt
2025-07-02 06:41:17.556
2025-07-02 06:41:17.556 # pump out diffs from after the synch point
2025-07-02 06:41:17.556 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.556
2025-07-02 06:41:17.556 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.556 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.556
2025-07-02 06:41:17.556 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.556 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.556 alo = 250, ahi = 1101
2025-07-02 06:41:17.556 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.556 blo = 250, bhi = 1101
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.557 g = []
2025-07-02 06:41:17.557 if alo < ahi:
2025-07-02 06:41:17.557 if blo < bhi:
2025-07-02 06:41:17.557 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.557 else:
2025-07-02 06:41:17.557 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.557 elif blo < bhi:
2025-07-02 06:41:17.557 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 > yield from g
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.557 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.557 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.557 alo = 250, ahi = 1101
2025-07-02 06:41:17.558 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.558 blo = 250, bhi = 1101
2025-07-02 06:41:17.558
2025-07-02 06:41:17.558 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.558 r"""
2025-07-02 06:41:17.558 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.558 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.558 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.558 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.558
2025-07-02 06:41:17.558 Example:
2025-07-02 06:41:17.558
2025-07-02 06:41:17.558 >>> d = Differ()
2025-07-02 06:41:17.558 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.558 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.558 >>> print(''.join(results), end="")
2025-07-02 06:41:17.558 - abcDefghiJkl
2025-07-02 06:41:17.558 + abcdefGhijkl
2025-07-02 06:41:17.559 """
2025-07-02 06:41:17.559
2025-07-02 06:41:17.559 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.559 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.559 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.559 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.559 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.559
2025-07-02 06:41:17.559 # search for the pair that matches best without being identical
2025-07-02 06:41:17.559 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.559 # on junk -- unless we have to)
2025-07-02 06:41:17.559 for j in range(blo, bhi):
2025-07-02 06:41:17.559 bj = b[j]
2025-07-02 06:41:17.559 cruncher.set_seq2(bj)
2025-07-02 06:41:17.559 for i in range(alo, ahi):
2025-07-02 06:41:17.559 ai = a[i]
2025-07-02 06:41:17.559 if ai == bj:
2025-07-02 06:41:17.559 if eqi is None:
2025-07-02 06:41:17.560 eqi, eqj = i, j
2025-07-02 06:41:17.560 continue
2025-07-02 06:41:17.560 cruncher.set_seq1(ai)
2025-07-02 06:41:17.560 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.560 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.560 # compares by a factor of 3.
2025-07-02 06:41:17.560 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.560 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.560 # of the computation is cached by cruncher
2025-07-02 06:41:17.560 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.560 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.560 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.560 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.560 if best_ratio < cutoff:
2025-07-02 06:41:17.560 # no non-identical "pretty close" pair
2025-07-02 06:41:17.560 if eqi is None:
2025-07-02 06:41:17.560 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.560 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.561 return
2025-07-02 06:41:17.561 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.561 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.561 else:
2025-07-02 06:41:17.561 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.561 eqi = None
2025-07-02 06:41:17.561
2025-07-02 06:41:17.561 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.561 # identical
2025-07-02 06:41:17.561
2025-07-02 06:41:17.561 # pump out diffs from before the synch point
2025-07-02 06:41:17.561 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.561
2025-07-02 06:41:17.561 # do intraline marking on the synch pair
2025-07-02 06:41:17.561 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.561 if eqi is None:
2025-07-02 06:41:17.561 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.561 atags = btags = ""
2025-07-02 06:41:17.561 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.561 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.562 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.562 if tag == 'replace':
2025-07-02 06:41:17.562 atags += '^' * la
2025-07-02 06:41:17.562 btags += '^' * lb
2025-07-02 06:41:17.562 elif tag == 'delete':
2025-07-02 06:41:17.562 atags += '-' * la
2025-07-02 06:41:17.562 elif tag == 'insert':
2025-07-02 06:41:17.562 btags += '+' * lb
2025-07-02 06:41:17.562 elif tag == 'equal':
2025-07-02 06:41:17.562 atags += ' ' * la
2025-07-02 06:41:17.562 btags += ' ' * lb
2025-07-02 06:41:17.562 else:
2025-07-02 06:41:17.562 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.562 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.562 else:
2025-07-02 06:41:17.562 # the synch pair is identical
2025-07-02 06:41:17.562 yield ' ' + aelt
2025-07-02 06:41:17.562
2025-07-02 06:41:17.562 # pump out diffs from after the synch point
2025-07-02 06:41:17.563 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.563
2025-07-02 06:41:17.563 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.563 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.563
2025-07-02 06:41:17.563 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.563 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.563 alo = 251, ahi = 1101
2025-07-02 06:41:17.563 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.563 blo = 251, bhi = 1101
2025-07-02 06:41:17.563
2025-07-02 06:41:17.563 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.563 g = []
2025-07-02 06:41:17.563 if alo < ahi:
2025-07-02 06:41:17.563 if blo < bhi:
2025-07-02 06:41:17.563 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.563 else:
2025-07-02 06:41:17.563 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.563 elif blo < bhi:
2025-07-02 06:41:17.564 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 > yield from g
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.564 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.564 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.564 alo = 251, ahi = 1101
2025-07-02 06:41:17.564 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.564 blo = 251, bhi = 1101
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.564 r"""
2025-07-02 06:41:17.564 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.564 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.564 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.564 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.564
2025-07-02 06:41:17.565 Example:
2025-07-02 06:41:17.565
2025-07-02 06:41:17.565 >>> d = Differ()
2025-07-02 06:41:17.565 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.565 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.565 >>> print(''.join(results), end="")
2025-07-02 06:41:17.565 - abcDefghiJkl
2025-07-02 06:41:17.565 + abcdefGhijkl
2025-07-02 06:41:17.565 """
2025-07-02 06:41:17.565
2025-07-02 06:41:17.565 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.565 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.565 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.565 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.565 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.565
2025-07-02 06:41:17.565 # search for the pair that matches best without being identical
2025-07-02 06:41:17.565 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.566 # on junk -- unless we have to)
2025-07-02 06:41:17.566 for j in range(blo, bhi):
2025-07-02 06:41:17.566 bj = b[j]
2025-07-02 06:41:17.566 cruncher.set_seq2(bj)
2025-07-02 06:41:17.566 for i in range(alo, ahi):
2025-07-02 06:41:17.566 ai = a[i]
2025-07-02 06:41:17.566 if ai == bj:
2025-07-02 06:41:17.566 if eqi is None:
2025-07-02 06:41:17.566 eqi, eqj = i, j
2025-07-02 06:41:17.566 continue
2025-07-02 06:41:17.566 cruncher.set_seq1(ai)
2025-07-02 06:41:17.566 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.566 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.566 # compares by a factor of 3.
2025-07-02 06:41:17.566 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.566 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.566 # of the computation is cached by cruncher
2025-07-02 06:41:17.566 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.566 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.567 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.567 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.567 if best_ratio < cutoff:
2025-07-02 06:41:17.567 # no non-identical "pretty close" pair
2025-07-02 06:41:17.567 if eqi is None:
2025-07-02 06:41:17.567 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.567 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.567 return
2025-07-02 06:41:17.567 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.567 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.567 else:
2025-07-02 06:41:17.567 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.567 eqi = None
2025-07-02 06:41:17.567
2025-07-02 06:41:17.567 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.567 # identical
2025-07-02 06:41:17.567
2025-07-02 06:41:17.567 # pump out diffs from before the synch point
2025-07-02 06:41:17.567 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.568
2025-07-02 06:41:17.568 # do intraline marking on the synch pair
2025-07-02 06:41:17.568 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.568 if eqi is None:
2025-07-02 06:41:17.568 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.568 atags = btags = ""
2025-07-02 06:41:17.568 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.568 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.568 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.568 if tag == 'replace':
2025-07-02 06:41:17.568 atags += '^' * la
2025-07-02 06:41:17.568 btags += '^' * lb
2025-07-02 06:41:17.568 elif tag == 'delete':
2025-07-02 06:41:17.568 atags += '-' * la
2025-07-02 06:41:17.568 elif tag == 'insert':
2025-07-02 06:41:17.568 btags += '+' * lb
2025-07-02 06:41:17.568 elif tag == 'equal':
2025-07-02 06:41:17.568 atags += ' ' * la
2025-07-02 06:41:17.569 btags += ' ' * lb
2025-07-02 06:41:17.569 else:
2025-07-02 06:41:17.569 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.569 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.569 else:
2025-07-02 06:41:17.569 # the synch pair is identical
2025-07-02 06:41:17.569 yield ' ' + aelt
2025-07-02 06:41:17.569
2025-07-02 06:41:17.569 # pump out diffs from after the synch point
2025-07-02 06:41:17.569 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.569
2025-07-02 06:41:17.569 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.569 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.569
2025-07-02 06:41:17.569 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.569 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.569 alo = 252, ahi = 1101
2025-07-02 06:41:17.569 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.569 blo = 252, bhi = 1101
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.570 g = []
2025-07-02 06:41:17.570 if alo < ahi:
2025-07-02 06:41:17.570 if blo < bhi:
2025-07-02 06:41:17.570 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.570 else:
2025-07-02 06:41:17.570 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.570 elif blo < bhi:
2025-07-02 06:41:17.570 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 > yield from g
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.570 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.570 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.570 alo = 252, ahi = 1101
2025-07-02 06:41:17.570 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.571 blo = 252, bhi = 1101
2025-07-02 06:41:17.571
2025-07-02 06:41:17.571 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.571 r"""
2025-07-02 06:41:17.571 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.571 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.571 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.571 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.571
2025-07-02 06:41:17.571 Example:
2025-07-02 06:41:17.571
2025-07-02 06:41:17.571 >>> d = Differ()
2025-07-02 06:41:17.571 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.571 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.571 >>> print(''.join(results), end="")
2025-07-02 06:41:17.571 - abcDefghiJkl
2025-07-02 06:41:17.571 + abcdefGhijkl
2025-07-02 06:41:17.572 """
2025-07-02 06:41:17.572
2025-07-02 06:41:17.572 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.572 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.572 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.572 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.572 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.572
2025-07-02 06:41:17.572 # search for the pair that matches best without being identical
2025-07-02 06:41:17.572 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.572 # on junk -- unless we have to)
2025-07-02 06:41:17.572 for j in range(blo, bhi):
2025-07-02 06:41:17.572 bj = b[j]
2025-07-02 06:41:17.572 cruncher.set_seq2(bj)
2025-07-02 06:41:17.572 for i in range(alo, ahi):
2025-07-02 06:41:17.572 ai = a[i]
2025-07-02 06:41:17.572 if ai == bj:
2025-07-02 06:41:17.572 if eqi is None:
2025-07-02 06:41:17.572 eqi, eqj = i, j
2025-07-02 06:41:17.572 continue
2025-07-02 06:41:17.573 cruncher.set_seq1(ai)
2025-07-02 06:41:17.573 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.573 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.573 # compares by a factor of 3.
2025-07-02 06:41:17.573 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.573 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.573 # of the computation is cached by cruncher
2025-07-02 06:41:17.573 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.573 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.573 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.573 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.573 if best_ratio < cutoff:
2025-07-02 06:41:17.573 # no non-identical "pretty close" pair
2025-07-02 06:41:17.573 if eqi is None:
2025-07-02 06:41:17.573 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.573 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.573 return
2025-07-02 06:41:17.573 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.573 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.574 else:
2025-07-02 06:41:17.574 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.574 eqi = None
2025-07-02 06:41:17.574
2025-07-02 06:41:17.574 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.574 # identical
2025-07-02 06:41:17.574
2025-07-02 06:41:17.574 # pump out diffs from before the synch point
2025-07-02 06:41:17.574 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.574
2025-07-02 06:41:17.574 # do intraline marking on the synch pair
2025-07-02 06:41:17.574 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.574 if eqi is None:
2025-07-02 06:41:17.574 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.574 atags = btags = ""
2025-07-02 06:41:17.574 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.574 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.574 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.574 if tag == 'replace':
2025-07-02 06:41:17.574 atags += '^' * la
2025-07-02 06:41:17.575 btags += '^' * lb
2025-07-02 06:41:17.575 elif tag == 'delete':
2025-07-02 06:41:17.575 atags += '-' * la
2025-07-02 06:41:17.575 elif tag == 'insert':
2025-07-02 06:41:17.575 btags += '+' * lb
2025-07-02 06:41:17.575 elif tag == 'equal':
2025-07-02 06:41:17.575 atags += ' ' * la
2025-07-02 06:41:17.575 btags += ' ' * lb
2025-07-02 06:41:17.575 else:
2025-07-02 06:41:17.575 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.575 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.575 else:
2025-07-02 06:41:17.575 # the synch pair is identical
2025-07-02 06:41:17.575 yield ' ' + aelt
2025-07-02 06:41:17.575
2025-07-02 06:41:17.575 # pump out diffs from after the synch point
2025-07-02 06:41:17.575 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.575
2025-07-02 06:41:17.575 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.576 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.576
2025-07-02 06:41:17.576 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.576 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.576 alo = 253, ahi = 1101
2025-07-02 06:41:17.576 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.576 blo = 253, bhi = 1101
2025-07-02 06:41:17.576
2025-07-02 06:41:17.576 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.576 g = []
2025-07-02 06:41:17.576 if alo < ahi:
2025-07-02 06:41:17.576 if blo < bhi:
2025-07-02 06:41:17.576 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.576 else:
2025-07-02 06:41:17.576 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.576 elif blo < bhi:
2025-07-02 06:41:17.576 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.576
2025-07-02 06:41:17.576 > yield from g
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.577 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.577 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.577 alo = 253, ahi = 1101
2025-07-02 06:41:17.577 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.577 blo = 253, bhi = 1101
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.577 r"""
2025-07-02 06:41:17.577 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.577 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.577 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.577 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577 Example:
2025-07-02 06:41:17.578
2025-07-02 06:41:17.578 >>> d = Differ()
2025-07-02 06:41:17.578 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.578 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.578 >>> print(''.join(results), end="")
2025-07-02 06:41:17.578 - abcDefghiJkl
2025-07-02 06:41:17.578 + abcdefGhijkl
2025-07-02 06:41:17.578 """
2025-07-02 06:41:17.578
2025-07-02 06:41:17.578 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.578 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.578 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.578 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.578 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.578
2025-07-02 06:41:17.578 # search for the pair that matches best without being identical
2025-07-02 06:41:17.578 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.578 # on junk -- unless we have to)
2025-07-02 06:41:17.579 for j in range(blo, bhi):
2025-07-02 06:41:17.579 bj = b[j]
2025-07-02 06:41:17.579 cruncher.set_seq2(bj)
2025-07-02 06:41:17.579 for i in range(alo, ahi):
2025-07-02 06:41:17.579 ai = a[i]
2025-07-02 06:41:17.579 if ai == bj:
2025-07-02 06:41:17.579 if eqi is None:
2025-07-02 06:41:17.579 eqi, eqj = i, j
2025-07-02 06:41:17.579 continue
2025-07-02 06:41:17.579 cruncher.set_seq1(ai)
2025-07-02 06:41:17.579 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.579 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.579 # compares by a factor of 3.
2025-07-02 06:41:17.579 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.579 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.579 # of the computation is cached by cruncher
2025-07-02 06:41:17.579 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.579 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.579 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.580 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.580 if best_ratio < cutoff:
2025-07-02 06:41:17.580 # no non-identical "pretty close" pair
2025-07-02 06:41:17.580 if eqi is None:
2025-07-02 06:41:17.580 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.580 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.580 return
2025-07-02 06:41:17.580 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.580 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.580 else:
2025-07-02 06:41:17.580 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.580 eqi = None
2025-07-02 06:41:17.580
2025-07-02 06:41:17.580 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.580 # identical
2025-07-02 06:41:17.580
2025-07-02 06:41:17.580 # pump out diffs from before the synch point
2025-07-02 06:41:17.580 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.580
2025-07-02 06:41:17.580 # do intraline marking on the synch pair
2025-07-02 06:41:17.581 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.581 if eqi is None:
2025-07-02 06:41:17.581 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.581 atags = btags = ""
2025-07-02 06:41:17.581 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.581 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.581 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.581 if tag == 'replace':
2025-07-02 06:41:17.581 atags += '^' * la
2025-07-02 06:41:17.581 btags += '^' * lb
2025-07-02 06:41:17.581 elif tag == 'delete':
2025-07-02 06:41:17.581 atags += '-' * la
2025-07-02 06:41:17.581 elif tag == 'insert':
2025-07-02 06:41:17.581 btags += '+' * lb
2025-07-02 06:41:17.581 elif tag == 'equal':
2025-07-02 06:41:17.581 atags += ' ' * la
2025-07-02 06:41:17.581 btags += ' ' * lb
2025-07-02 06:41:17.581 else:
2025-07-02 06:41:17.581 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.582 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.582 else:
2025-07-02 06:41:17.582 # the synch pair is identical
2025-07-02 06:41:17.582 yield ' ' + aelt
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582 # pump out diffs from after the synch point
2025-07-02 06:41:17.582 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.582 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.582 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.582 alo = 254, ahi = 1101
2025-07-02 06:41:17.582 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.582 blo = 254, bhi = 1101
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.582 g = []
2025-07-02 06:41:17.582 if alo < ahi:
2025-07-02 06:41:17.583 if blo < bhi:
2025-07-02 06:41:17.583 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.583 else:
2025-07-02 06:41:17.583 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.583 elif blo < bhi:
2025-07-02 06:41:17.583 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.583
2025-07-02 06:41:17.583 > yield from g
2025-07-02 06:41:17.583
2025-07-02 06:41:17.583 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.583 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.583
2025-07-02 06:41:17.583 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.583 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.583 alo = 254, ahi = 1101
2025-07-02 06:41:17.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.583 blo = 254, bhi = 1101
2025-07-02 06:41:17.583
2025-07-02 06:41:17.584 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.584 r"""
2025-07-02 06:41:17.584 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.584 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.584 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.584 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.584
2025-07-02 06:41:17.584 Example:
2025-07-02 06:41:17.584
2025-07-02 06:41:17.584 >>> d = Differ()
2025-07-02 06:41:17.584 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.584 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.584 >>> print(''.join(results), end="")
2025-07-02 06:41:17.584 - abcDefghiJkl
2025-07-02 06:41:17.584 + abcdefGhijkl
2025-07-02 06:41:17.584 """
2025-07-02 06:41:17.584
2025-07-02 06:41:17.585 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.585 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.585 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.585 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.585 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.585
2025-07-02 06:41:17.585 # search for the pair that matches best without being identical
2025-07-02 06:41:17.585 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.585 # on junk -- unless we have to)
2025-07-02 06:41:17.585 for j in range(blo, bhi):
2025-07-02 06:41:17.585 bj = b[j]
2025-07-02 06:41:17.585 cruncher.set_seq2(bj)
2025-07-02 06:41:17.585 for i in range(alo, ahi):
2025-07-02 06:41:17.585 ai = a[i]
2025-07-02 06:41:17.585 if ai == bj:
2025-07-02 06:41:17.585 if eqi is None:
2025-07-02 06:41:17.585 eqi, eqj = i, j
2025-07-02 06:41:17.585 continue
2025-07-02 06:41:17.585 cruncher.set_seq1(ai)
2025-07-02 06:41:17.586 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.586 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.586 # compares by a factor of 3.
2025-07-02 06:41:17.586 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.586 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.586 # of the computation is cached by cruncher
2025-07-02 06:41:17.586 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.586 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.586 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.586 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.586 if best_ratio < cutoff:
2025-07-02 06:41:17.586 # no non-identical "pretty close" pair
2025-07-02 06:41:17.586 if eqi is None:
2025-07-02 06:41:17.586 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.586 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.586 return
2025-07-02 06:41:17.586 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.586 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.586 else:
2025-07-02 06:41:17.587 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.587 eqi = None
2025-07-02 06:41:17.587
2025-07-02 06:41:17.587 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.587 # identical
2025-07-02 06:41:17.587
2025-07-02 06:41:17.587 # pump out diffs from before the synch point
2025-07-02 06:41:17.587 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.587
2025-07-02 06:41:17.587 # do intraline marking on the synch pair
2025-07-02 06:41:17.587 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.587 if eqi is None:
2025-07-02 06:41:17.587 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.587 atags = btags = ""
2025-07-02 06:41:17.587 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.587 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.587 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.587 if tag == 'replace':
2025-07-02 06:41:17.587 atags += '^' * la
2025-07-02 06:41:17.588 btags += '^' * lb
2025-07-02 06:41:17.588 elif tag == 'delete':
2025-07-02 06:41:17.588 atags += '-' * la
2025-07-02 06:41:17.588 elif tag == 'insert':
2025-07-02 06:41:17.588 btags += '+' * lb
2025-07-02 06:41:17.588 elif tag == 'equal':
2025-07-02 06:41:17.588 atags += ' ' * la
2025-07-02 06:41:17.588 btags += ' ' * lb
2025-07-02 06:41:17.588 else:
2025-07-02 06:41:17.588 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.588 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.588 else:
2025-07-02 06:41:17.588 # the synch pair is identical
2025-07-02 06:41:17.588 yield ' ' + aelt
2025-07-02 06:41:17.588
2025-07-02 06:41:17.588 # pump out diffs from after the synch point
2025-07-02 06:41:17.588 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.588
2025-07-02 06:41:17.588 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.588 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.589
2025-07-02 06:41:17.589 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.589 alo = 255, ahi = 1101
2025-07-02 06:41:17.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.589 blo = 255, bhi = 1101
2025-07-02 06:41:17.589
2025-07-02 06:41:17.589 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.589 g = []
2025-07-02 06:41:17.589 if alo < ahi:
2025-07-02 06:41:17.589 if blo < bhi:
2025-07-02 06:41:17.589 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.589 else:
2025-07-02 06:41:17.589 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.589 elif blo < bhi:
2025-07-02 06:41:17.589 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.589
2025-07-02 06:41:17.589 > yield from g
2025-07-02 06:41:17.589
2025-07-02 06:41:17.590 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.590 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.590 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.590 alo = 255, ahi = 1101
2025-07-02 06:41:17.590 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.590 blo = 255, bhi = 1101
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.590 r"""
2025-07-02 06:41:17.590 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.590 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.590 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.590 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590 Example:
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590 >>> d = Differ()
2025-07-02 06:41:17.591 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.591 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.591 >>> print(''.join(results), end="")
2025-07-02 06:41:17.591 - abcDefghiJkl
2025-07-02 06:41:17.591 + abcdefGhijkl
2025-07-02 06:41:17.591 """
2025-07-02 06:41:17.591
2025-07-02 06:41:17.591 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.591 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.591 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.591 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.591 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.591
2025-07-02 06:41:17.591 # search for the pair that matches best without being identical
2025-07-02 06:41:17.591 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.591 # on junk -- unless we have to)
2025-07-02 06:41:17.591 for j in range(blo, bhi):
2025-07-02 06:41:17.591 bj = b[j]
2025-07-02 06:41:17.592 cruncher.set_seq2(bj)
2025-07-02 06:41:17.592 for i in range(alo, ahi):
2025-07-02 06:41:17.592 ai = a[i]
2025-07-02 06:41:17.592 if ai == bj:
2025-07-02 06:41:17.592 if eqi is None:
2025-07-02 06:41:17.592 eqi, eqj = i, j
2025-07-02 06:41:17.592 continue
2025-07-02 06:41:17.592 cruncher.set_seq1(ai)
2025-07-02 06:41:17.592 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.592 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.592 # compares by a factor of 3.
2025-07-02 06:41:17.592 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.592 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.592 # of the computation is cached by cruncher
2025-07-02 06:41:17.592 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.592 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.592 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.592 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.592 if best_ratio < cutoff:
2025-07-02 06:41:17.593 # no non-identical "pretty close" pair
2025-07-02 06:41:17.593 if eqi is None:
2025-07-02 06:41:17.593 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.593 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.593 return
2025-07-02 06:41:17.593 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.593 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.593 else:
2025-07-02 06:41:17.593 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.593 eqi = None
2025-07-02 06:41:17.593
2025-07-02 06:41:17.593 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.593 # identical
2025-07-02 06:41:17.593
2025-07-02 06:41:17.593 # pump out diffs from before the synch point
2025-07-02 06:41:17.593 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.593
2025-07-02 06:41:17.593 # do intraline marking on the synch pair
2025-07-02 06:41:17.593 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.593 if eqi is None:
2025-07-02 06:41:17.594 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.594 atags = btags = ""
2025-07-02 06:41:17.594 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.594 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.594 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.594 if tag == 'replace':
2025-07-02 06:41:17.594 atags += '^' * la
2025-07-02 06:41:17.594 btags += '^' * lb
2025-07-02 06:41:17.594 elif tag == 'delete':
2025-07-02 06:41:17.594 atags += '-' * la
2025-07-02 06:41:17.594 elif tag == 'insert':
2025-07-02 06:41:17.594 btags += '+' * lb
2025-07-02 06:41:17.594 elif tag == 'equal':
2025-07-02 06:41:17.594 atags += ' ' * la
2025-07-02 06:41:17.594 btags += ' ' * lb
2025-07-02 06:41:17.594 else:
2025-07-02 06:41:17.594 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.594 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.594 else:
2025-07-02 06:41:17.595 # the synch pair is identical
2025-07-02 06:41:17.595 yield ' ' + aelt
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595 # pump out diffs from after the synch point
2025-07-02 06:41:17.595 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.595 alo = 256, ahi = 1101
2025-07-02 06:41:17.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.595 blo = 256, bhi = 1101
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.595 g = []
2025-07-02 06:41:17.595 if alo < ahi:
2025-07-02 06:41:17.596 if blo < bhi:
2025-07-02 06:41:17.596 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.596 else:
2025-07-02 06:41:17.596 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.596 elif blo < bhi:
2025-07-02 06:41:17.596 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 > yield from g
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.596 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.596 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.596 alo = 256, ahi = 1101
2025-07-02 06:41:17.596 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.596 blo = 256, bhi = 1101
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.597 r"""
2025-07-02 06:41:17.597 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.597 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.597 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.597 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.597
2025-07-02 06:41:17.597 Example:
2025-07-02 06:41:17.597
2025-07-02 06:41:17.597 >>> d = Differ()
2025-07-02 06:41:17.597 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.597 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.597 >>> print(''.join(results), end="")
2025-07-02 06:41:17.597 - abcDefghiJkl
2025-07-02 06:41:17.597 + abcdefGhijkl
2025-07-02 06:41:17.597 """
2025-07-02 06:41:17.597
2025-07-02 06:41:17.597 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.597 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.598 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.598 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.598 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.598
2025-07-02 06:41:17.598 # search for the pair that matches best without being identical
2025-07-02 06:41:17.598 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.598 # on junk -- unless we have to)
2025-07-02 06:41:17.598 for j in range(blo, bhi):
2025-07-02 06:41:17.598 bj = b[j]
2025-07-02 06:41:17.598 cruncher.set_seq2(bj)
2025-07-02 06:41:17.598 for i in range(alo, ahi):
2025-07-02 06:41:17.598 ai = a[i]
2025-07-02 06:41:17.598 if ai == bj:
2025-07-02 06:41:17.598 if eqi is None:
2025-07-02 06:41:17.598 eqi, eqj = i, j
2025-07-02 06:41:17.598 continue
2025-07-02 06:41:17.598 cruncher.set_seq1(ai)
2025-07-02 06:41:17.598 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.598 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.599 # compares by a factor of 3.
2025-07-02 06:41:17.599 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.599 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.599 # of the computation is cached by cruncher
2025-07-02 06:41:17.599 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.599 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.599 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.599 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.599 if best_ratio < cutoff:
2025-07-02 06:41:17.599 # no non-identical "pretty close" pair
2025-07-02 06:41:17.599 if eqi is None:
2025-07-02 06:41:17.599 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.599 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.599 return
2025-07-02 06:41:17.599 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.599 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.599 else:
2025-07-02 06:41:17.599 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.600 eqi = None
2025-07-02 06:41:17.600
2025-07-02 06:41:17.600 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.600 # identical
2025-07-02 06:41:17.600
2025-07-02 06:41:17.600 # pump out diffs from before the synch point
2025-07-02 06:41:17.600 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.600
2025-07-02 06:41:17.600 # do intraline marking on the synch pair
2025-07-02 06:41:17.600 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.600 if eqi is None:
2025-07-02 06:41:17.600 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.600 atags = btags = ""
2025-07-02 06:41:17.600 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.600 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.600 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.600 if tag == 'replace':
2025-07-02 06:41:17.600 atags += '^' * la
2025-07-02 06:41:17.601 btags += '^' * lb
2025-07-02 06:41:17.601 elif tag == 'delete':
2025-07-02 06:41:17.601 atags += '-' * la
2025-07-02 06:41:17.601 elif tag == 'insert':
2025-07-02 06:41:17.601 btags += '+' * lb
2025-07-02 06:41:17.601 elif tag == 'equal':
2025-07-02 06:41:17.601 atags += ' ' * la
2025-07-02 06:41:17.601 btags += ' ' * lb
2025-07-02 06:41:17.601 else:
2025-07-02 06:41:17.601 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.601 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.601 else:
2025-07-02 06:41:17.601 # the synch pair is identical
2025-07-02 06:41:17.601 yield ' ' + aelt
2025-07-02 06:41:17.601
2025-07-02 06:41:17.601 # pump out diffs from after the synch point
2025-07-02 06:41:17.601 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.601
2025-07-02 06:41:17.601 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.602 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.602
2025-07-02 06:41:17.602 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.602 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.602 alo = 257, ahi = 1101
2025-07-02 06:41:17.602 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.602 blo = 257, bhi = 1101
2025-07-02 06:41:17.602
2025-07-02 06:41:17.602 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.602 g = []
2025-07-02 06:41:17.602 if alo < ahi:
2025-07-02 06:41:17.602 if blo < bhi:
2025-07-02 06:41:17.602 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.602 else:
2025-07-02 06:41:17.602 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.602 elif blo < bhi:
2025-07-02 06:41:17.602 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.602
2025-07-02 06:41:17.602 > yield from g
2025-07-02 06:41:17.603
2025-07-02 06:41:17.603 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.603 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.603
2025-07-02 06:41:17.603 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.603 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.603 alo = 257, ahi = 1101
2025-07-02 06:41:17.603 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.603 blo = 257, bhi = 1101
2025-07-02 06:41:17.603
2025-07-02 06:41:17.603 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.603 r"""
2025-07-02 06:41:17.603 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.603 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.603 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.603 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.603
2025-07-02 06:41:17.604 Example:
2025-07-02 06:41:17.604
2025-07-02 06:41:17.604 >>> d = Differ()
2025-07-02 06:41:17.604 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.604 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.604 >>> print(''.join(results), end="")
2025-07-02 06:41:17.604 - abcDefghiJkl
2025-07-02 06:41:17.604 + abcdefGhijkl
2025-07-02 06:41:17.604 """
2025-07-02 06:41:17.604
2025-07-02 06:41:17.604 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.604 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.604 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.604 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.604 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.604
2025-07-02 06:41:17.605 # search for the pair that matches best without being identical
2025-07-02 06:41:17.605 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.605 # on junk -- unless we have to)
2025-07-02 06:41:17.605 for j in range(blo, bhi):
2025-07-02 06:41:17.605 bj = b[j]
2025-07-02 06:41:17.605 cruncher.set_seq2(bj)
2025-07-02 06:41:17.605 for i in range(alo, ahi):
2025-07-02 06:41:17.605 ai = a[i]
2025-07-02 06:41:17.605 if ai == bj:
2025-07-02 06:41:17.605 if eqi is None:
2025-07-02 06:41:17.605 eqi, eqj = i, j
2025-07-02 06:41:17.605 continue
2025-07-02 06:41:17.605 cruncher.set_seq1(ai)
2025-07-02 06:41:17.605 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.605 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.605 # compares by a factor of 3.
2025-07-02 06:41:17.605 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.605 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.606 # of the computation is cached by cruncher
2025-07-02 06:41:17.606 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.606 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.606 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.606 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.606 if best_ratio < cutoff:
2025-07-02 06:41:17.606 # no non-identical "pretty close" pair
2025-07-02 06:41:17.606 if eqi is None:
2025-07-02 06:41:17.606 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.606 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.606 return
2025-07-02 06:41:17.606 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.606 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.606 else:
2025-07-02 06:41:17.606 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.606 eqi = None
2025-07-02 06:41:17.606
2025-07-02 06:41:17.606 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.606 # identical
2025-07-02 06:41:17.607
2025-07-02 06:41:17.607 # pump out diffs from before the synch point
2025-07-02 06:41:17.607 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.607
2025-07-02 06:41:17.607 # do intraline marking on the synch pair
2025-07-02 06:41:17.607 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.607 if eqi is None:
2025-07-02 06:41:17.607 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.607 atags = btags = ""
2025-07-02 06:41:17.607 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.607 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.607 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.607 if tag == 'replace':
2025-07-02 06:41:17.607 atags += '^' * la
2025-07-02 06:41:17.607 btags += '^' * lb
2025-07-02 06:41:17.607 elif tag == 'delete':
2025-07-02 06:41:17.607 atags += '-' * la
2025-07-02 06:41:17.607 elif tag == 'insert':
2025-07-02 06:41:17.607 btags += '+' * lb
2025-07-02 06:41:17.608 elif tag == 'equal':
2025-07-02 06:41:17.608 atags += ' ' * la
2025-07-02 06:41:17.608 btags += ' ' * lb
2025-07-02 06:41:17.608 else:
2025-07-02 06:41:17.608 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.608 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.608 else:
2025-07-02 06:41:17.608 # the synch pair is identical
2025-07-02 06:41:17.608 yield ' ' + aelt
2025-07-02 06:41:17.608
2025-07-02 06:41:17.608 # pump out diffs from after the synch point
2025-07-02 06:41:17.608 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.608
2025-07-02 06:41:17.608 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.608 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.608
2025-07-02 06:41:17.608 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.608 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.609 alo = 258, ahi = 1101
2025-07-02 06:41:17.609 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.609 blo = 258, bhi = 1101
2025-07-02 06:41:17.609
2025-07-02 06:41:17.609 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.609 g = []
2025-07-02 06:41:17.609 if alo < ahi:
2025-07-02 06:41:17.609 if blo < bhi:
2025-07-02 06:41:17.609 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.609 else:
2025-07-02 06:41:17.609 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.609 elif blo < bhi:
2025-07-02 06:41:17.609 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.609
2025-07-02 06:41:17.609 > yield from g
2025-07-02 06:41:17.609
2025-07-02 06:41:17.609 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.609 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.609
2025-07-02 06:41:17.610 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.610 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.610 alo = 258, ahi = 1101
2025-07-02 06:41:17.610 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.610 blo = 258, bhi = 1101
2025-07-02 06:41:17.610
2025-07-02 06:41:17.610 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.610 r"""
2025-07-02 06:41:17.610 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.610 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.610 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.610 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.610
2025-07-02 06:41:17.610 Example:
2025-07-02 06:41:17.610
2025-07-02 06:41:17.610 >>> d = Differ()
2025-07-02 06:41:17.610 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.610 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.611 >>> print(''.join(results), end="")
2025-07-02 06:41:17.611 - abcDefghiJkl
2025-07-02 06:41:17.611 + abcdefGhijkl
2025-07-02 06:41:17.611 """
2025-07-02 06:41:17.611
2025-07-02 06:41:17.611 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.611 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.611 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.611 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.611 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.611
2025-07-02 06:41:17.611 # search for the pair that matches best without being identical
2025-07-02 06:41:17.611 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.611 # on junk -- unless we have to)
2025-07-02 06:41:17.611 for j in range(blo, bhi):
2025-07-02 06:41:17.611 bj = b[j]
2025-07-02 06:41:17.611 cruncher.set_seq2(bj)
2025-07-02 06:41:17.612 for i in range(alo, ahi):
2025-07-02 06:41:17.612 ai = a[i]
2025-07-02 06:41:17.612 if ai == bj:
2025-07-02 06:41:17.612 if eqi is None:
2025-07-02 06:41:17.612 eqi, eqj = i, j
2025-07-02 06:41:17.612 continue
2025-07-02 06:41:17.612 cruncher.set_seq1(ai)
2025-07-02 06:41:17.612 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.612 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.612 # compares by a factor of 3.
2025-07-02 06:41:17.612 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.612 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.612 # of the computation is cached by cruncher
2025-07-02 06:41:17.612 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.612 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.612 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.612 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.612 if best_ratio < cutoff:
2025-07-02 06:41:17.612 # no non-identical "pretty close" pair
2025-07-02 06:41:17.613 if eqi is None:
2025-07-02 06:41:17.613 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.613 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.613 return
2025-07-02 06:41:17.613 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.613 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.613 else:
2025-07-02 06:41:17.613 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.613 eqi = None
2025-07-02 06:41:17.613
2025-07-02 06:41:17.613 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.613 # identical
2025-07-02 06:41:17.613
2025-07-02 06:41:17.613 # pump out diffs from before the synch point
2025-07-02 06:41:17.613 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.613
2025-07-02 06:41:17.613 # do intraline marking on the synch pair
2025-07-02 06:41:17.614 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.614 if eqi is None:
2025-07-02 06:41:17.614 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.614 atags = btags = ""
2025-07-02 06:41:17.614 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.614 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.614 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.614 if tag == 'replace':
2025-07-02 06:41:17.614 atags += '^' * la
2025-07-02 06:41:17.614 btags += '^' * lb
2025-07-02 06:41:17.614 elif tag == 'delete':
2025-07-02 06:41:17.614 atags += '-' * la
2025-07-02 06:41:17.614 elif tag == 'insert':
2025-07-02 06:41:17.614 btags += '+' * lb
2025-07-02 06:41:17.614 elif tag == 'equal':
2025-07-02 06:41:17.614 atags += ' ' * la
2025-07-02 06:41:17.614 btags += ' ' * lb
2025-07-02 06:41:17.614 else:
2025-07-02 06:41:17.614 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.614 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.615 else:
2025-07-02 06:41:17.615 # the synch pair is identical
2025-07-02 06:41:17.615 yield ' ' + aelt
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615 # pump out diffs from after the synch point
2025-07-02 06:41:17.615 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.615 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.615 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.615 alo = 259, ahi = 1101
2025-07-02 06:41:17.615 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.615 blo = 259, bhi = 1101
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.616 g = []
2025-07-02 06:41:17.616 if alo < ahi:
2025-07-02 06:41:17.616 if blo < bhi:
2025-07-02 06:41:17.616 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.616 else:
2025-07-02 06:41:17.616 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.616 elif blo < bhi:
2025-07-02 06:41:17.616 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.616
2025-07-02 06:41:17.616 > yield from g
2025-07-02 06:41:17.616
2025-07-02 06:41:17.616 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.616 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.616
2025-07-02 06:41:17.616 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.616 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.616 alo = 259, ahi = 1101
2025-07-02 06:41:17.616 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.616 blo = 259, bhi = 1101
2025-07-02 06:41:17.616
2025-07-02 06:41:17.617 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.617 r"""
2025-07-02 06:41:17.617 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.617 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.617 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.617 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.617
2025-07-02 06:41:17.617 Example:
2025-07-02 06:41:17.617
2025-07-02 06:41:17.617 >>> d = Differ()
2025-07-02 06:41:17.617 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.617 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.617 >>> print(''.join(results), end="")
2025-07-02 06:41:17.617 - abcDefghiJkl
2025-07-02 06:41:17.617 + abcdefGhijkl
2025-07-02 06:41:17.617 """
2025-07-02 06:41:17.617
2025-07-02 06:41:17.617 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.617 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.618 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.618 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.618 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.618
2025-07-02 06:41:17.618 # search for the pair that matches best without being identical
2025-07-02 06:41:17.618 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.618 # on junk -- unless we have to)
2025-07-02 06:41:17.618 for j in range(blo, bhi):
2025-07-02 06:41:17.618 bj = b[j]
2025-07-02 06:41:17.618 cruncher.set_seq2(bj)
2025-07-02 06:41:17.618 for i in range(alo, ahi):
2025-07-02 06:41:17.618 ai = a[i]
2025-07-02 06:41:17.618 if ai == bj:
2025-07-02 06:41:17.618 if eqi is None:
2025-07-02 06:41:17.618 eqi, eqj = i, j
2025-07-02 06:41:17.618 continue
2025-07-02 06:41:17.618 cruncher.set_seq1(ai)
2025-07-02 06:41:17.618 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.618 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.618 # compares by a factor of 3.
2025-07-02 06:41:17.619 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.619 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.619 # of the computation is cached by cruncher
2025-07-02 06:41:17.619 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.619 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.619 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.619 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.619 if best_ratio < cutoff:
2025-07-02 06:41:17.619 # no non-identical "pretty close" pair
2025-07-02 06:41:17.619 if eqi is None:
2025-07-02 06:41:17.619 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.619 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.619 return
2025-07-02 06:41:17.619 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.619 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.619 else:
2025-07-02 06:41:17.619 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.619 eqi = None
2025-07-02 06:41:17.619
2025-07-02 06:41:17.619 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.620 # identical
2025-07-02 06:41:17.620
2025-07-02 06:41:17.620 # pump out diffs from before the synch point
2025-07-02 06:41:17.620 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.620
2025-07-02 06:41:17.620 # do intraline marking on the synch pair
2025-07-02 06:41:17.620 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.620 if eqi is None:
2025-07-02 06:41:17.620 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.620 atags = btags = ""
2025-07-02 06:41:17.620 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.620 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.620 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.620 if tag == 'replace':
2025-07-02 06:41:17.620 atags += '^' * la
2025-07-02 06:41:17.620 btags += '^' * lb
2025-07-02 06:41:17.620 elif tag == 'delete':
2025-07-02 06:41:17.620 atags += '-' * la
2025-07-02 06:41:17.620 elif tag == 'insert':
2025-07-02 06:41:17.620 btags += '+' * lb
2025-07-02 06:41:17.620 elif tag == 'equal':
2025-07-02 06:41:17.621 atags += ' ' * la
2025-07-02 06:41:17.621 btags += ' ' * lb
2025-07-02 06:41:17.621 else:
2025-07-02 06:41:17.621 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.621 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.621 else:
2025-07-02 06:41:17.621 # the synch pair is identical
2025-07-02 06:41:17.621 yield ' ' + aelt
2025-07-02 06:41:17.621
2025-07-02 06:41:17.621 # pump out diffs from after the synch point
2025-07-02 06:41:17.621 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.621
2025-07-02 06:41:17.621 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.621 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.621
2025-07-02 06:41:17.621 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.621 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.621 alo = 260, ahi = 1101
2025-07-02 06:41:17.621 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.622 blo = 260, bhi = 1101
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.622 g = []
2025-07-02 06:41:17.622 if alo < ahi:
2025-07-02 06:41:17.622 if blo < bhi:
2025-07-02 06:41:17.622 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.622 else:
2025-07-02 06:41:17.622 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.622 elif blo < bhi:
2025-07-02 06:41:17.622 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 > yield from g
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.622 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.622 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.623 alo = 260, ahi = 1101
2025-07-02 06:41:17.623 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.623 blo = 260, bhi = 1101
2025-07-02 06:41:17.623
2025-07-02 06:41:17.623 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.623 r"""
2025-07-02 06:41:17.623 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.623 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.623 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.623 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.623
2025-07-02 06:41:17.623 Example:
2025-07-02 06:41:17.623
2025-07-02 06:41:17.623 >>> d = Differ()
2025-07-02 06:41:17.623 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.623 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.623 >>> print(''.join(results), end="")
2025-07-02 06:41:17.623 - abcDefghiJkl
2025-07-02 06:41:17.624 + abcdefGhijkl
2025-07-02 06:41:17.624 """
2025-07-02 06:41:17.624
2025-07-02 06:41:17.624 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.624 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.624 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.624 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.624 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.624
2025-07-02 06:41:17.624 # search for the pair that matches best without being identical
2025-07-02 06:41:17.624 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.624 # on junk -- unless we have to)
2025-07-02 06:41:17.624 for j in range(blo, bhi):
2025-07-02 06:41:17.624 bj = b[j]
2025-07-02 06:41:17.624 cruncher.set_seq2(bj)
2025-07-02 06:41:17.624 for i in range(alo, ahi):
2025-07-02 06:41:17.624 ai = a[i]
2025-07-02 06:41:17.624 if ai == bj:
2025-07-02 06:41:17.624 if eqi is None:
2025-07-02 06:41:17.624 eqi, eqj = i, j
2025-07-02 06:41:17.625 continue
2025-07-02 06:41:17.625 cruncher.set_seq1(ai)
2025-07-02 06:41:17.625 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.625 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.625 # compares by a factor of 3.
2025-07-02 06:41:17.625 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.625 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.625 # of the computation is cached by cruncher
2025-07-02 06:41:17.625 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.625 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.625 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.625 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.625 if best_ratio < cutoff:
2025-07-02 06:41:17.625 # no non-identical "pretty close" pair
2025-07-02 06:41:17.625 if eqi is None:
2025-07-02 06:41:17.625 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.625 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.625 return
2025-07-02 06:41:17.625 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.625 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.626 else:
2025-07-02 06:41:17.626 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.626 eqi = None
2025-07-02 06:41:17.626
2025-07-02 06:41:17.626 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.626 # identical
2025-07-02 06:41:17.626
2025-07-02 06:41:17.626 # pump out diffs from before the synch point
2025-07-02 06:41:17.626 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.626
2025-07-02 06:41:17.626 # do intraline marking on the synch pair
2025-07-02 06:41:17.626 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.626 if eqi is None:
2025-07-02 06:41:17.626 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.626 atags = btags = ""
2025-07-02 06:41:17.626 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.626 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.626 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.626 if tag == 'replace':
2025-07-02 06:41:17.626 atags += '^' * la
2025-07-02 06:41:17.627 btags += '^' * lb
2025-07-02 06:41:17.627 elif tag == 'delete':
2025-07-02 06:41:17.627 atags += '-' * la
2025-07-02 06:41:17.627 elif tag == 'insert':
2025-07-02 06:41:17.627 btags += '+' * lb
2025-07-02 06:41:17.627 elif tag == 'equal':
2025-07-02 06:41:17.627 atags += ' ' * la
2025-07-02 06:41:17.627 btags += ' ' * lb
2025-07-02 06:41:17.627 else:
2025-07-02 06:41:17.627 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.627 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.627 else:
2025-07-02 06:41:17.627 # the synch pair is identical
2025-07-02 06:41:17.627 yield ' ' + aelt
2025-07-02 06:41:17.627
2025-07-02 06:41:17.627 # pump out diffs from after the synch point
2025-07-02 06:41:17.627 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.627
2025-07-02 06:41:17.627 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.627 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.627
2025-07-02 06:41:17.628 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.628 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.628 alo = 261, ahi = 1101
2025-07-02 06:41:17.628 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.628 blo = 261, bhi = 1101
2025-07-02 06:41:17.628
2025-07-02 06:41:17.628 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.628 g = []
2025-07-02 06:41:17.628 if alo < ahi:
2025-07-02 06:41:17.628 if blo < bhi:
2025-07-02 06:41:17.628 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.628 else:
2025-07-02 06:41:17.628 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.628 elif blo < bhi:
2025-07-02 06:41:17.628 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.628
2025-07-02 06:41:17.628 > yield from g
2025-07-02 06:41:17.628
2025-07-02 06:41:17.628 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.628 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.629 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.629 alo = 261, ahi = 1101
2025-07-02 06:41:17.629 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.629 blo = 261, bhi = 1101
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.629 r"""
2025-07-02 06:41:17.629 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.629 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.629 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.629 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629 Example:
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629 >>> d = Differ()
2025-07-02 06:41:17.629 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.629 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.629 >>> print(''.join(results), end="")
2025-07-02 06:41:17.630 - abcDefghiJkl
2025-07-02 06:41:17.630 + abcdefGhijkl
2025-07-02 06:41:17.630 """
2025-07-02 06:41:17.630
2025-07-02 06:41:17.630 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.630 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.630 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.630 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.630 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.630
2025-07-02 06:41:17.630 # search for the pair that matches best without being identical
2025-07-02 06:41:17.630 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.630 # on junk -- unless we have to)
2025-07-02 06:41:17.630 for j in range(blo, bhi):
2025-07-02 06:41:17.630 bj = b[j]
2025-07-02 06:41:17.630 cruncher.set_seq2(bj)
2025-07-02 06:41:17.630 for i in range(alo, ahi):
2025-07-02 06:41:17.630 ai = a[i]
2025-07-02 06:41:17.631 if ai == bj:
2025-07-02 06:41:17.631 if eqi is None:
2025-07-02 06:41:17.631 eqi, eqj = i, j
2025-07-02 06:41:17.631 continue
2025-07-02 06:41:17.631 cruncher.set_seq1(ai)
2025-07-02 06:41:17.631 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.631 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.631 # compares by a factor of 3.
2025-07-02 06:41:17.631 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.631 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.631 # of the computation is cached by cruncher
2025-07-02 06:41:17.631 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.631 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.631 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.631 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.631 if best_ratio < cutoff:
2025-07-02 06:41:17.631 # no non-identical "pretty close" pair
2025-07-02 06:41:17.631 if eqi is None:
2025-07-02 06:41:17.632 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.632 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.632 return
2025-07-02 06:41:17.632 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.632 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.632 else:
2025-07-02 06:41:17.632 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.632 eqi = None
2025-07-02 06:41:17.632
2025-07-02 06:41:17.632 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.632 # identical
2025-07-02 06:41:17.632
2025-07-02 06:41:17.632 # pump out diffs from before the synch point
2025-07-02 06:41:17.632 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.632
2025-07-02 06:41:17.632 # do intraline marking on the synch pair
2025-07-02 06:41:17.632 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.632 if eqi is None:
2025-07-02 06:41:17.632 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.632 atags = btags = ""
2025-07-02 06:41:17.633 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.633 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.633 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.633 if tag == 'replace':
2025-07-02 06:41:17.633 atags += '^' * la
2025-07-02 06:41:17.633 btags += '^' * lb
2025-07-02 06:41:17.633 elif tag == 'delete':
2025-07-02 06:41:17.633 atags += '-' * la
2025-07-02 06:41:17.633 elif tag == 'insert':
2025-07-02 06:41:17.633 btags += '+' * lb
2025-07-02 06:41:17.633 elif tag == 'equal':
2025-07-02 06:41:17.633 atags += ' ' * la
2025-07-02 06:41:17.633 btags += ' ' * lb
2025-07-02 06:41:17.633 else:
2025-07-02 06:41:17.633 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.633 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.633 else:
2025-07-02 06:41:17.633 # the synch pair is identical
2025-07-02 06:41:17.633 yield ' ' + aelt
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634 # pump out diffs from after the synch point
2025-07-02 06:41:17.634 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.634 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.634 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.634 alo = 262, ahi = 1101
2025-07-02 06:41:17.634 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.634 blo = 262, bhi = 1101
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.634 g = []
2025-07-02 06:41:17.634 if alo < ahi:
2025-07-02 06:41:17.634 if blo < bhi:
2025-07-02 06:41:17.634 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.634 else:
2025-07-02 06:41:17.634 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.635 elif blo < bhi:
2025-07-02 06:41:17.635 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 > yield from g
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.635 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.635 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.635 alo = 262, ahi = 1101
2025-07-02 06:41:17.635 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.635 blo = 262, bhi = 1101
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.635 r"""
2025-07-02 06:41:17.635 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.635 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.636 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.636 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.636
2025-07-02 06:41:17.636 Example:
2025-07-02 06:41:17.636
2025-07-02 06:41:17.636 >>> d = Differ()
2025-07-02 06:41:17.636 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.636 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.636 >>> print(''.join(results), end="")
2025-07-02 06:41:17.636 - abcDefghiJkl
2025-07-02 06:41:17.636 + abcdefGhijkl
2025-07-02 06:41:17.636 """
2025-07-02 06:41:17.636
2025-07-02 06:41:17.636 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.636 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.636 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.636 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.636 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.637
2025-07-02 06:41:17.637 # search for the pair that matches best without being identical
2025-07-02 06:41:17.637 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.637 # on junk -- unless we have to)
2025-07-02 06:41:17.637 for j in range(blo, bhi):
2025-07-02 06:41:17.637 bj = b[j]
2025-07-02 06:41:17.637 cruncher.set_seq2(bj)
2025-07-02 06:41:17.637 for i in range(alo, ahi):
2025-07-02 06:41:17.637 ai = a[i]
2025-07-02 06:41:17.637 if ai == bj:
2025-07-02 06:41:17.637 if eqi is None:
2025-07-02 06:41:17.637 eqi, eqj = i, j
2025-07-02 06:41:17.637 continue
2025-07-02 06:41:17.637 cruncher.set_seq1(ai)
2025-07-02 06:41:17.637 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.637 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.637 # compares by a factor of 3.
2025-07-02 06:41:17.637 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.637 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.637 # of the computation is cached by cruncher
2025-07-02 06:41:17.638 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.638 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.638 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.638 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.638 if best_ratio < cutoff:
2025-07-02 06:41:17.638 # no non-identical "pretty close" pair
2025-07-02 06:41:17.638 if eqi is None:
2025-07-02 06:41:17.638 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.638 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.638 return
2025-07-02 06:41:17.638 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.638 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.638 else:
2025-07-02 06:41:17.638 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.638 eqi = None
2025-07-02 06:41:17.638
2025-07-02 06:41:17.638 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.638 # identical
2025-07-02 06:41:17.638
2025-07-02 06:41:17.638 # pump out diffs from before the synch point
2025-07-02 06:41:17.639 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.639
2025-07-02 06:41:17.639 # do intraline marking on the synch pair
2025-07-02 06:41:17.639 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.639 if eqi is None:
2025-07-02 06:41:17.639 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.639 atags = btags = ""
2025-07-02 06:41:17.639 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.639 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.639 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.639 if tag == 'replace':
2025-07-02 06:41:17.639 atags += '^' * la
2025-07-02 06:41:17.639 btags += '^' * lb
2025-07-02 06:41:17.639 elif tag == 'delete':
2025-07-02 06:41:17.639 atags += '-' * la
2025-07-02 06:41:17.639 elif tag == 'insert':
2025-07-02 06:41:17.639 btags += '+' * lb
2025-07-02 06:41:17.639 elif tag == 'equal':
2025-07-02 06:41:17.639 atags += ' ' * la
2025-07-02 06:41:17.640 btags += ' ' * lb
2025-07-02 06:41:17.640 else:
2025-07-02 06:41:17.640 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.640 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.640 else:
2025-07-02 06:41:17.640 # the synch pair is identical
2025-07-02 06:41:17.640 yield ' ' + aelt
2025-07-02 06:41:17.640
2025-07-02 06:41:17.640 # pump out diffs from after the synch point
2025-07-02 06:41:17.640 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.640
2025-07-02 06:41:17.640 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.640 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.640
2025-07-02 06:41:17.640 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.640 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.640 alo = 263, ahi = 1101
2025-07-02 06:41:17.640 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.640 blo = 263, bhi = 1101
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.641 g = []
2025-07-02 06:41:17.641 if alo < ahi:
2025-07-02 06:41:17.641 if blo < bhi:
2025-07-02 06:41:17.641 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.641 else:
2025-07-02 06:41:17.641 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.641 elif blo < bhi:
2025-07-02 06:41:17.641 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 > yield from g
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.641 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.641 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.641 alo = 263, ahi = 1101
2025-07-02 06:41:17.641 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.642 blo = 263, bhi = 1101
2025-07-02 06:41:17.642
2025-07-02 06:41:17.642 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.642 r"""
2025-07-02 06:41:17.642 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.642 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.642 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.642 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.642
2025-07-02 06:41:17.642 Example:
2025-07-02 06:41:17.642
2025-07-02 06:41:17.642 >>> d = Differ()
2025-07-02 06:41:17.642 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.642 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.642 >>> print(''.join(results), end="")
2025-07-02 06:41:17.642 - abcDefghiJkl
2025-07-02 06:41:17.642 + abcdefGhijkl
2025-07-02 06:41:17.642 """
2025-07-02 06:41:17.643
2025-07-02 06:41:17.643 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.643 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.643 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.643 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.643 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.643
2025-07-02 06:41:17.643 # search for the pair that matches best without being identical
2025-07-02 06:41:17.643 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.643 # on junk -- unless we have to)
2025-07-02 06:41:17.643 for j in range(blo, bhi):
2025-07-02 06:41:17.643 bj = b[j]
2025-07-02 06:41:17.643 cruncher.set_seq2(bj)
2025-07-02 06:41:17.643 for i in range(alo, ahi):
2025-07-02 06:41:17.643 ai = a[i]
2025-07-02 06:41:17.643 if ai == bj:
2025-07-02 06:41:17.643 if eqi is None:
2025-07-02 06:41:17.643 eqi, eqj = i, j
2025-07-02 06:41:17.644 continue
2025-07-02 06:41:17.644 cruncher.set_seq1(ai)
2025-07-02 06:41:17.644 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.644 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.644 # compares by a factor of 3.
2025-07-02 06:41:17.644 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.644 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.644 # of the computation is cached by cruncher
2025-07-02 06:41:17.644 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.644 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.644 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.644 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.644 if best_ratio < cutoff:
2025-07-02 06:41:17.644 # no non-identical "pretty close" pair
2025-07-02 06:41:17.644 if eqi is None:
2025-07-02 06:41:17.644 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.644 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.644 return
2025-07-02 06:41:17.644 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.644 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.645 else:
2025-07-02 06:41:17.645 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.645 eqi = None
2025-07-02 06:41:17.645
2025-07-02 06:41:17.645 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.645 # identical
2025-07-02 06:41:17.645
2025-07-02 06:41:17.645 # pump out diffs from before the synch point
2025-07-02 06:41:17.645 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.645
2025-07-02 06:41:17.645 # do intraline marking on the synch pair
2025-07-02 06:41:17.645 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.645 if eqi is None:
2025-07-02 06:41:17.645 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.645 atags = btags = ""
2025-07-02 06:41:17.645 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.645 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.645 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.645 if tag == 'replace':
2025-07-02 06:41:17.645 atags += '^' * la
2025-07-02 06:41:17.646 btags += '^' * lb
2025-07-02 06:41:17.646 elif tag == 'delete':
2025-07-02 06:41:17.646 atags += '-' * la
2025-07-02 06:41:17.646 elif tag == 'insert':
2025-07-02 06:41:17.646 btags += '+' * lb
2025-07-02 06:41:17.646 elif tag == 'equal':
2025-07-02 06:41:17.646 atags += ' ' * la
2025-07-02 06:41:17.646 btags += ' ' * lb
2025-07-02 06:41:17.646 else:
2025-07-02 06:41:17.646 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.646 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.646 else:
2025-07-02 06:41:17.646 # the synch pair is identical
2025-07-02 06:41:17.646 yield ' ' + aelt
2025-07-02 06:41:17.646
2025-07-02 06:41:17.646 # pump out diffs from after the synch point
2025-07-02 06:41:17.646 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.646
2025-07-02 06:41:17.646 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.647 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.647
2025-07-02 06:41:17.647 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.647 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.647 alo = 264, ahi = 1101
2025-07-02 06:41:17.647 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.647 blo = 264, bhi = 1101
2025-07-02 06:41:17.647
2025-07-02 06:41:17.647 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.647 g = []
2025-07-02 06:41:17.647 if alo < ahi:
2025-07-02 06:41:17.647 if blo < bhi:
2025-07-02 06:41:17.647 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.647 else:
2025-07-02 06:41:17.647 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.647 elif blo < bhi:
2025-07-02 06:41:17.647 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.647
2025-07-02 06:41:17.647 > yield from g
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.648 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.648 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.648 alo = 264, ahi = 1101
2025-07-02 06:41:17.648 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.648 blo = 264, bhi = 1101
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.648 r"""
2025-07-02 06:41:17.648 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.648 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.648 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.648 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648 Example:
2025-07-02 06:41:17.649
2025-07-02 06:41:17.649 >>> d = Differ()
2025-07-02 06:41:17.649 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.649 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.649 >>> print(''.join(results), end="")
2025-07-02 06:41:17.649 - abcDefghiJkl
2025-07-02 06:41:17.649 + abcdefGhijkl
2025-07-02 06:41:17.649 """
2025-07-02 06:41:17.649
2025-07-02 06:41:17.649 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.649 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.649 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.649 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.649 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.649
2025-07-02 06:41:17.649 # search for the pair that matches best without being identical
2025-07-02 06:41:17.649 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.650 # on junk -- unless we have to)
2025-07-02 06:41:17.650 for j in range(blo, bhi):
2025-07-02 06:41:17.650 bj = b[j]
2025-07-02 06:41:17.650 cruncher.set_seq2(bj)
2025-07-02 06:41:17.650 for i in range(alo, ahi):
2025-07-02 06:41:17.650 ai = a[i]
2025-07-02 06:41:17.650 if ai == bj:
2025-07-02 06:41:17.650 if eqi is None:
2025-07-02 06:41:17.650 eqi, eqj = i, j
2025-07-02 06:41:17.650 continue
2025-07-02 06:41:17.650 cruncher.set_seq1(ai)
2025-07-02 06:41:17.650 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.650 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.650 # compares by a factor of 3.
2025-07-02 06:41:17.650 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.650 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.650 # of the computation is cached by cruncher
2025-07-02 06:41:17.650 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.650 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.650 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.651 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.651 if best_ratio < cutoff:
2025-07-02 06:41:17.651 # no non-identical "pretty close" pair
2025-07-02 06:41:17.651 if eqi is None:
2025-07-02 06:41:17.651 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.651 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.651 return
2025-07-02 06:41:17.651 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.651 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.651 else:
2025-07-02 06:41:17.651 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.651 eqi = None
2025-07-02 06:41:17.651
2025-07-02 06:41:17.651 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.651 # identical
2025-07-02 06:41:17.651
2025-07-02 06:41:17.651 # pump out diffs from before the synch point
2025-07-02 06:41:17.651 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.651
2025-07-02 06:41:17.651 # do intraline marking on the synch pair
2025-07-02 06:41:17.652 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.652 if eqi is None:
2025-07-02 06:41:17.652 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.652 atags = btags = ""
2025-07-02 06:41:17.652 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.652 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.652 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.652 if tag == 'replace':
2025-07-02 06:41:17.652 atags += '^' * la
2025-07-02 06:41:17.652 btags += '^' * lb
2025-07-02 06:41:17.652 elif tag == 'delete':
2025-07-02 06:41:17.652 atags += '-' * la
2025-07-02 06:41:17.652 elif tag == 'insert':
2025-07-02 06:41:17.652 btags += '+' * lb
2025-07-02 06:41:17.652 elif tag == 'equal':
2025-07-02 06:41:17.652 atags += ' ' * la
2025-07-02 06:41:17.652 btags += ' ' * lb
2025-07-02 06:41:17.652 else:
2025-07-02 06:41:17.652 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.652 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.652 else:
2025-07-02 06:41:17.653 # the synch pair is identical
2025-07-02 06:41:17.653 yield ' ' + aelt
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653 # pump out diffs from after the synch point
2025-07-02 06:41:17.653 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.653 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.653 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.653 alo = 265, ahi = 1101
2025-07-02 06:41:17.653 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.653 blo = 265, bhi = 1101
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.653 g = []
2025-07-02 06:41:17.653 if alo < ahi:
2025-07-02 06:41:17.653 if blo < bhi:
2025-07-02 06:41:17.653 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.654 else:
2025-07-02 06:41:17.654 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.654 elif blo < bhi:
2025-07-02 06:41:17.654 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 > yield from g
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.654 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.654 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.654 alo = 265, ahi = 1101
2025-07-02 06:41:17.654 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.654 blo = 265, bhi = 1101
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.654 r"""
2025-07-02 06:41:17.654 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.654 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.655 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.655 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.655
2025-07-02 06:41:17.655 Example:
2025-07-02 06:41:17.655
2025-07-02 06:41:17.655 >>> d = Differ()
2025-07-02 06:41:17.655 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.655 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.655 >>> print(''.join(results), end="")
2025-07-02 06:41:17.655 - abcDefghiJkl
2025-07-02 06:41:17.655 + abcdefGhijkl
2025-07-02 06:41:17.655 """
2025-07-02 06:41:17.655
2025-07-02 06:41:17.655 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.655 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.655 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.655 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.656 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.656
2025-07-02 06:41:17.656 # search for the pair that matches best without being identical
2025-07-02 06:41:17.656 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.656 # on junk -- unless we have to)
2025-07-02 06:41:17.656 for j in range(blo, bhi):
2025-07-02 06:41:17.656 bj = b[j]
2025-07-02 06:41:17.656 cruncher.set_seq2(bj)
2025-07-02 06:41:17.656 for i in range(alo, ahi):
2025-07-02 06:41:17.656 ai = a[i]
2025-07-02 06:41:17.656 if ai == bj:
2025-07-02 06:41:17.656 if eqi is None:
2025-07-02 06:41:17.656 eqi, eqj = i, j
2025-07-02 06:41:17.656 continue
2025-07-02 06:41:17.656 cruncher.set_seq1(ai)
2025-07-02 06:41:17.656 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.656 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.656 # compares by a factor of 3.
2025-07-02 06:41:17.656 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.657 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.657 # of the computation is cached by cruncher
2025-07-02 06:41:17.657 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.657 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.657 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.657 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.657 if best_ratio < cutoff:
2025-07-02 06:41:17.657 # no non-identical "pretty close" pair
2025-07-02 06:41:17.657 if eqi is None:
2025-07-02 06:41:17.657 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.657 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.657 return
2025-07-02 06:41:17.657 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.657 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.657 else:
2025-07-02 06:41:17.657 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.657 eqi = None
2025-07-02 06:41:17.657
2025-07-02 06:41:17.657 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.658 # identical
2025-07-02 06:41:17.658
2025-07-02 06:41:17.658 # pump out diffs from before the synch point
2025-07-02 06:41:17.658 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.658
2025-07-02 06:41:17.658 # do intraline marking on the synch pair
2025-07-02 06:41:17.658 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.658 if eqi is None:
2025-07-02 06:41:17.658 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.658 atags = btags = ""
2025-07-02 06:41:17.658 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.658 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.658 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.658 if tag == 'replace':
2025-07-02 06:41:17.658 atags += '^' * la
2025-07-02 06:41:17.658 btags += '^' * lb
2025-07-02 06:41:17.658 elif tag == 'delete':
2025-07-02 06:41:17.658 atags += '-' * la
2025-07-02 06:41:17.658 elif tag == 'insert':
2025-07-02 06:41:17.658 btags += '+' * lb
2025-07-02 06:41:17.659 elif tag == 'equal':
2025-07-02 06:41:17.659 atags += ' ' * la
2025-07-02 06:41:17.659 btags += ' ' * lb
2025-07-02 06:41:17.659 else:
2025-07-02 06:41:17.659 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.659 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.659 else:
2025-07-02 06:41:17.659 # the synch pair is identical
2025-07-02 06:41:17.659 yield ' ' + aelt
2025-07-02 06:41:17.659
2025-07-02 06:41:17.659 # pump out diffs from after the synch point
2025-07-02 06:41:17.659 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.659
2025-07-02 06:41:17.659 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.659 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.659
2025-07-02 06:41:17.659 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.659 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.659 alo = 268, ahi = 1101
2025-07-02 06:41:17.659 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.660 blo = 268, bhi = 1101
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.660 g = []
2025-07-02 06:41:17.660 if alo < ahi:
2025-07-02 06:41:17.660 if blo < bhi:
2025-07-02 06:41:17.660 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.660 else:
2025-07-02 06:41:17.660 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.660 elif blo < bhi:
2025-07-02 06:41:17.660 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 > yield from g
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.660 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.660 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.660 alo = 268, ahi = 1101
2025-07-02 06:41:17.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.661 blo = 268, bhi = 1101
2025-07-02 06:41:17.661
2025-07-02 06:41:17.661 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.661 r"""
2025-07-02 06:41:17.661 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.661 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.661 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.661 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.661
2025-07-02 06:41:17.661 Example:
2025-07-02 06:41:17.661
2025-07-02 06:41:17.661 >>> d = Differ()
2025-07-02 06:41:17.661 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.661 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.661 >>> print(''.join(results), end="")
2025-07-02 06:41:17.661 - abcDefghiJkl
2025-07-02 06:41:17.662 + abcdefGhijkl
2025-07-02 06:41:17.662 """
2025-07-02 06:41:17.662
2025-07-02 06:41:17.662 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.662 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.662 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.662 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.662 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.662
2025-07-02 06:41:17.662 # search for the pair that matches best without being identical
2025-07-02 06:41:17.662 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.662 # on junk -- unless we have to)
2025-07-02 06:41:17.662 for j in range(blo, bhi):
2025-07-02 06:41:17.662 bj = b[j]
2025-07-02 06:41:17.662 cruncher.set_seq2(bj)
2025-07-02 06:41:17.662 for i in range(alo, ahi):
2025-07-02 06:41:17.662 ai = a[i]
2025-07-02 06:41:17.662 if ai == bj:
2025-07-02 06:41:17.663 if eqi is None:
2025-07-02 06:41:17.663 eqi, eqj = i, j
2025-07-02 06:41:17.663 continue
2025-07-02 06:41:17.663 cruncher.set_seq1(ai)
2025-07-02 06:41:17.663 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.663 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.663 # compares by a factor of 3.
2025-07-02 06:41:17.663 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.663 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.663 # of the computation is cached by cruncher
2025-07-02 06:41:17.663 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.663 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.663 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.663 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.663 if best_ratio < cutoff:
2025-07-02 06:41:17.663 # no non-identical "pretty close" pair
2025-07-02 06:41:17.663 if eqi is None:
2025-07-02 06:41:17.663 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.663 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.663 return
2025-07-02 06:41:17.664 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.664 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.664 else:
2025-07-02 06:41:17.664 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.664 eqi = None
2025-07-02 06:41:17.664
2025-07-02 06:41:17.664 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.664 # identical
2025-07-02 06:41:17.664
2025-07-02 06:41:17.664 # pump out diffs from before the synch point
2025-07-02 06:41:17.664 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.664
2025-07-02 06:41:17.664 # do intraline marking on the synch pair
2025-07-02 06:41:17.664 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.664 if eqi is None:
2025-07-02 06:41:17.664 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.664 atags = btags = ""
2025-07-02 06:41:17.664 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.664 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.664 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.665 if tag == 'replace':
2025-07-02 06:41:17.665 atags += '^' * la
2025-07-02 06:41:17.665 btags += '^' * lb
2025-07-02 06:41:17.665 elif tag == 'delete':
2025-07-02 06:41:17.665 atags += '-' * la
2025-07-02 06:41:17.665 elif tag == 'insert':
2025-07-02 06:41:17.665 btags += '+' * lb
2025-07-02 06:41:17.665 elif tag == 'equal':
2025-07-02 06:41:17.665 atags += ' ' * la
2025-07-02 06:41:17.665 btags += ' ' * lb
2025-07-02 06:41:17.665 else:
2025-07-02 06:41:17.665 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.665 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.665 else:
2025-07-02 06:41:17.665 # the synch pair is identical
2025-07-02 06:41:17.665 yield ' ' + aelt
2025-07-02 06:41:17.665
2025-07-02 06:41:17.665 # pump out diffs from after the synch point
2025-07-02 06:41:17.665 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.666
2025-07-02 06:41:17.666 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.666 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.666
2025-07-02 06:41:17.666 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.666 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.666 alo = 269, ahi = 1101
2025-07-02 06:41:17.666 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.666 blo = 269, bhi = 1101
2025-07-02 06:41:17.666
2025-07-02 06:41:17.666 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.666 g = []
2025-07-02 06:41:17.666 if alo < ahi:
2025-07-02 06:41:17.666 if blo < bhi:
2025-07-02 06:41:17.666 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.666 else:
2025-07-02 06:41:17.666 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.666 elif blo < bhi:
2025-07-02 06:41:17.666 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 > yield from g
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.667 alo = 269, ahi = 1101
2025-07-02 06:41:17.667 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.667 blo = 269, bhi = 1101
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.667 r"""
2025-07-02 06:41:17.667 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.667 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.667 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.667 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.667
2025-07-02 06:41:17.668 Example:
2025-07-02 06:41:17.668
2025-07-02 06:41:17.668 >>> d = Differ()
2025-07-02 06:41:17.668 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.668 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.668 >>> print(''.join(results), end="")
2025-07-02 06:41:17.668 - abcDefghiJkl
2025-07-02 06:41:17.668 + abcdefGhijkl
2025-07-02 06:41:17.668 """
2025-07-02 06:41:17.668
2025-07-02 06:41:17.668 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.668 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.668 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.668 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.668 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.668
2025-07-02 06:41:17.668 # search for the pair that matches best without being identical
2025-07-02 06:41:17.668 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.668 # on junk -- unless we have to)
2025-07-02 06:41:17.669 for j in range(blo, bhi):
2025-07-02 06:41:17.669 bj = b[j]
2025-07-02 06:41:17.669 cruncher.set_seq2(bj)
2025-07-02 06:41:17.669 for i in range(alo, ahi):
2025-07-02 06:41:17.669 ai = a[i]
2025-07-02 06:41:17.669 if ai == bj:
2025-07-02 06:41:17.669 if eqi is None:
2025-07-02 06:41:17.669 eqi, eqj = i, j
2025-07-02 06:41:17.669 continue
2025-07-02 06:41:17.669 cruncher.set_seq1(ai)
2025-07-02 06:41:17.669 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.669 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.669 # compares by a factor of 3.
2025-07-02 06:41:17.669 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.669 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.669 # of the computation is cached by cruncher
2025-07-02 06:41:17.669 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.669 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.669 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.669 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.670 if best_ratio < cutoff:
2025-07-02 06:41:17.670 # no non-identical "pretty close" pair
2025-07-02 06:41:17.670 if eqi is None:
2025-07-02 06:41:17.670 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.670 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.670 return
2025-07-02 06:41:17.670 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.670 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.670 else:
2025-07-02 06:41:17.670 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.670 eqi = None
2025-07-02 06:41:17.670
2025-07-02 06:41:17.670 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.670 # identical
2025-07-02 06:41:17.670
2025-07-02 06:41:17.670 # pump out diffs from before the synch point
2025-07-02 06:41:17.670 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.670
2025-07-02 06:41:17.670 # do intraline marking on the synch pair
2025-07-02 06:41:17.670 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.671 if eqi is None:
2025-07-02 06:41:17.671 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.671 atags = btags = ""
2025-07-02 06:41:17.671 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.671 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.671 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.671 if tag == 'replace':
2025-07-02 06:41:17.671 atags += '^' * la
2025-07-02 06:41:17.671 btags += '^' * lb
2025-07-02 06:41:17.671 elif tag == 'delete':
2025-07-02 06:41:17.671 atags += '-' * la
2025-07-02 06:41:17.671 elif tag == 'insert':
2025-07-02 06:41:17.671 btags += '+' * lb
2025-07-02 06:41:17.671 elif tag == 'equal':
2025-07-02 06:41:17.671 atags += ' ' * la
2025-07-02 06:41:17.671 btags += ' ' * lb
2025-07-02 06:41:17.671 else:
2025-07-02 06:41:17.671 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.671 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.671 else:
2025-07-02 06:41:17.671 # the synch pair is identical
2025-07-02 06:41:17.672 yield ' ' + aelt
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672 # pump out diffs from after the synch point
2025-07-02 06:41:17.672 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.672 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.672 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.672 alo = 270, ahi = 1101
2025-07-02 06:41:17.672 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.672 blo = 270, bhi = 1101
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.672 g = []
2025-07-02 06:41:17.672 if alo < ahi:
2025-07-02 06:41:17.672 if blo < bhi:
2025-07-02 06:41:17.672 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.672 else:
2025-07-02 06:41:17.673 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.673 elif blo < bhi:
2025-07-02 06:41:17.673 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 > yield from g
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.673 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.673 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.673 alo = 270, ahi = 1101
2025-07-02 06:41:17.673 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.673 blo = 270, bhi = 1101
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.673 r"""
2025-07-02 06:41:17.673 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.673 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.673 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.674 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.674
2025-07-02 06:41:17.674 Example:
2025-07-02 06:41:17.674
2025-07-02 06:41:17.674 >>> d = Differ()
2025-07-02 06:41:17.674 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.674 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.674 >>> print(''.join(results), end="")
2025-07-02 06:41:17.674 - abcDefghiJkl
2025-07-02 06:41:17.674 + abcdefGhijkl
2025-07-02 06:41:17.674 """
2025-07-02 06:41:17.674
2025-07-02 06:41:17.674 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.674 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.674 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.674 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.675 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.675
2025-07-02 06:41:17.675 # search for the pair that matches best without being identical
2025-07-02 06:41:17.675 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.675 # on junk -- unless we have to)
2025-07-02 06:41:17.675 for j in range(blo, bhi):
2025-07-02 06:41:17.675 bj = b[j]
2025-07-02 06:41:17.675 cruncher.set_seq2(bj)
2025-07-02 06:41:17.675 for i in range(alo, ahi):
2025-07-02 06:41:17.675 ai = a[i]
2025-07-02 06:41:17.675 if ai == bj:
2025-07-02 06:41:17.675 if eqi is None:
2025-07-02 06:41:17.675 eqi, eqj = i, j
2025-07-02 06:41:17.675 continue
2025-07-02 06:41:17.675 cruncher.set_seq1(ai)
2025-07-02 06:41:17.675 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.675 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.675 # compares by a factor of 3.
2025-07-02 06:41:17.675 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.676 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.676 # of the computation is cached by cruncher
2025-07-02 06:41:17.676 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.676 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.676 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.676 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.676 if best_ratio < cutoff:
2025-07-02 06:41:17.676 # no non-identical "pretty close" pair
2025-07-02 06:41:17.676 if eqi is None:
2025-07-02 06:41:17.676 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.676 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.676 return
2025-07-02 06:41:17.676 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.676 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.676 else:
2025-07-02 06:41:17.676 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.676 eqi = None
2025-07-02 06:41:17.676
2025-07-02 06:41:17.676 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.676 # identical
2025-07-02 06:41:17.677
2025-07-02 06:41:17.677 # pump out diffs from before the synch point
2025-07-02 06:41:17.677 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.677
2025-07-02 06:41:17.677 # do intraline marking on the synch pair
2025-07-02 06:41:17.677 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.677 if eqi is None:
2025-07-02 06:41:17.677 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.677 atags = btags = ""
2025-07-02 06:41:17.677 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.677 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.677 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.677 if tag == 'replace':
2025-07-02 06:41:17.677 atags += '^' * la
2025-07-02 06:41:17.677 btags += '^' * lb
2025-07-02 06:41:17.677 elif tag == 'delete':
2025-07-02 06:41:17.677 atags += '-' * la
2025-07-02 06:41:17.678 elif tag == 'insert':
2025-07-02 06:41:17.678 btags += '+' * lb
2025-07-02 06:41:17.678 elif tag == 'equal':
2025-07-02 06:41:17.678 atags += ' ' * la
2025-07-02 06:41:17.678 btags += ' ' * lb
2025-07-02 06:41:17.678 else:
2025-07-02 06:41:17.678 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.678 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.678 else:
2025-07-02 06:41:17.678 # the synch pair is identical
2025-07-02 06:41:17.678 yield ' ' + aelt
2025-07-02 06:41:17.678
2025-07-02 06:41:17.678 # pump out diffs from after the synch point
2025-07-02 06:41:17.678 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.678
2025-07-02 06:41:17.678 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.678 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.678
2025-07-02 06:41:17.678 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.678 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.679 alo = 271, ahi = 1101
2025-07-02 06:41:17.679 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.679 blo = 271, bhi = 1101
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.679 g = []
2025-07-02 06:41:17.679 if alo < ahi:
2025-07-02 06:41:17.679 if blo < bhi:
2025-07-02 06:41:17.679 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.679 else:
2025-07-02 06:41:17.679 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.679 elif blo < bhi:
2025-07-02 06:41:17.679 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 > yield from g
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.679 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.680 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.680 alo = 271, ahi = 1101
2025-07-02 06:41:17.680 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.680 blo = 271, bhi = 1101
2025-07-02 06:41:17.680
2025-07-02 06:41:17.680 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.680 r"""
2025-07-02 06:41:17.680 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.680 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.680 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.680 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.680
2025-07-02 06:41:17.680 Example:
2025-07-02 06:41:17.680
2025-07-02 06:41:17.680 >>> d = Differ()
2025-07-02 06:41:17.680 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.680 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.680 >>> print(''.join(results), end="")
2025-07-02 06:41:17.680 - abcDefghiJkl
2025-07-02 06:41:17.680 + abcdefGhijkl
2025-07-02 06:41:17.681 """
2025-07-02 06:41:17.681
2025-07-02 06:41:17.681 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.681 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.681 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.681 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.681 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.681
2025-07-02 06:41:17.681 # search for the pair that matches best without being identical
2025-07-02 06:41:17.681 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.681 # on junk -- unless we have to)
2025-07-02 06:41:17.681 for j in range(blo, bhi):
2025-07-02 06:41:17.681 bj = b[j]
2025-07-02 06:41:17.681 cruncher.set_seq2(bj)
2025-07-02 06:41:17.681 for i in range(alo, ahi):
2025-07-02 06:41:17.681 ai = a[i]
2025-07-02 06:41:17.681 if ai == bj:
2025-07-02 06:41:17.681 if eqi is None:
2025-07-02 06:41:17.681 eqi, eqj = i, j
2025-07-02 06:41:17.682 continue
2025-07-02 06:41:17.682 cruncher.set_seq1(ai)
2025-07-02 06:41:17.682 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.682 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.682 # compares by a factor of 3.
2025-07-02 06:41:17.682 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.682 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.682 # of the computation is cached by cruncher
2025-07-02 06:41:17.682 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.682 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.682 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.682 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.682 if best_ratio < cutoff:
2025-07-02 06:41:17.682 # no non-identical "pretty close" pair
2025-07-02 06:41:17.682 if eqi is None:
2025-07-02 06:41:17.682 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.682 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.682 return
2025-07-02 06:41:17.682 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.682 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.682 else:
2025-07-02 06:41:17.683 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.683 eqi = None
2025-07-02 06:41:17.683
2025-07-02 06:41:17.683 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.683 # identical
2025-07-02 06:41:17.683
2025-07-02 06:41:17.683 # pump out diffs from before the synch point
2025-07-02 06:41:17.683 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.683
2025-07-02 06:41:17.683 # do intraline marking on the synch pair
2025-07-02 06:41:17.683 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.683 if eqi is None:
2025-07-02 06:41:17.683 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.683 atags = btags = ""
2025-07-02 06:41:17.683 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.683 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.683 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.683 if tag == 'replace':
2025-07-02 06:41:17.684 atags += '^' * la
2025-07-02 06:41:17.684 btags += '^' * lb
2025-07-02 06:41:17.684 elif tag == 'delete':
2025-07-02 06:41:17.684 atags += '-' * la
2025-07-02 06:41:17.684 elif tag == 'insert':
2025-07-02 06:41:17.684 btags += '+' * lb
2025-07-02 06:41:17.684 elif tag == 'equal':
2025-07-02 06:41:17.684 atags += ' ' * la
2025-07-02 06:41:17.684 btags += ' ' * lb
2025-07-02 06:41:17.684 else:
2025-07-02 06:41:17.684 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.684 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.684 else:
2025-07-02 06:41:17.684 # the synch pair is identical
2025-07-02 06:41:17.684 yield ' ' + aelt
2025-07-02 06:41:17.684
2025-07-02 06:41:17.684 # pump out diffs from after the synch point
2025-07-02 06:41:17.684 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.684
2025-07-02 06:41:17.685 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.685 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.685
2025-07-02 06:41:17.685 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.685 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.685 alo = 272, ahi = 1101
2025-07-02 06:41:17.685 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.685 blo = 272, bhi = 1101
2025-07-02 06:41:17.685
2025-07-02 06:41:17.685 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.685 g = []
2025-07-02 06:41:17.685 if alo < ahi:
2025-07-02 06:41:17.685 if blo < bhi:
2025-07-02 06:41:17.685 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.685 else:
2025-07-02 06:41:17.685 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.685 elif blo < bhi:
2025-07-02 06:41:17.685 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.685
2025-07-02 06:41:17.685 > yield from g
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.686 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.686 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.686 alo = 272, ahi = 1101
2025-07-02 06:41:17.686 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.686 blo = 272, bhi = 1101
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.686 r"""
2025-07-02 06:41:17.686 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.686 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.686 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.686 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 Example:
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 >>> d = Differ()
2025-07-02 06:41:17.687 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.687 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.687 >>> print(''.join(results), end="")
2025-07-02 06:41:17.687 - abcDefghiJkl
2025-07-02 06:41:17.687 + abcdefGhijkl
2025-07-02 06:41:17.687 """
2025-07-02 06:41:17.687
2025-07-02 06:41:17.687 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.687 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.687 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.687 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.687 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.687
2025-07-02 06:41:17.687 # search for the pair that matches best without being identical
2025-07-02 06:41:17.687 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.687 # on junk -- unless we have to)
2025-07-02 06:41:17.687 for j in range(blo, bhi):
2025-07-02 06:41:17.687 bj = b[j]
2025-07-02 06:41:17.687 cruncher.set_seq2(bj)
2025-07-02 06:41:17.688 for i in range(alo, ahi):
2025-07-02 06:41:17.688 ai = a[i]
2025-07-02 06:41:17.688 if ai == bj:
2025-07-02 06:41:17.688 if eqi is None:
2025-07-02 06:41:17.688 eqi, eqj = i, j
2025-07-02 06:41:17.688 continue
2025-07-02 06:41:17.688 cruncher.set_seq1(ai)
2025-07-02 06:41:17.688 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.688 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.688 # compares by a factor of 3.
2025-07-02 06:41:17.688 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.688 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.688 # of the computation is cached by cruncher
2025-07-02 06:41:17.688 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.688 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.688 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.688 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.688 if best_ratio < cutoff:
2025-07-02 06:41:17.688 # no non-identical "pretty close" pair
2025-07-02 06:41:17.689 if eqi is None:
2025-07-02 06:41:17.689 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.689 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.689 return
2025-07-02 06:41:17.689 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.689 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.689 else:
2025-07-02 06:41:17.689 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.689 eqi = None
2025-07-02 06:41:17.689
2025-07-02 06:41:17.689 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.689 # identical
2025-07-02 06:41:17.689
2025-07-02 06:41:17.689 # pump out diffs from before the synch point
2025-07-02 06:41:17.689 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.689
2025-07-02 06:41:17.689 # do intraline marking on the synch pair
2025-07-02 06:41:17.689 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.689 if eqi is None:
2025-07-02 06:41:17.689 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.690 atags = btags = ""
2025-07-02 06:41:17.690 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.690 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.690 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.690 if tag == 'replace':
2025-07-02 06:41:17.690 atags += '^' * la
2025-07-02 06:41:17.690 btags += '^' * lb
2025-07-02 06:41:17.690 elif tag == 'delete':
2025-07-02 06:41:17.690 atags += '-' * la
2025-07-02 06:41:17.690 elif tag == 'insert':
2025-07-02 06:41:17.690 btags += '+' * lb
2025-07-02 06:41:17.690 elif tag == 'equal':
2025-07-02 06:41:17.690 atags += ' ' * la
2025-07-02 06:41:17.690 btags += ' ' * lb
2025-07-02 06:41:17.690 else:
2025-07-02 06:41:17.690 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.690 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.690 else:
2025-07-02 06:41:17.690 # the synch pair is identical
2025-07-02 06:41:17.690 yield ' ' + aelt
2025-07-02 06:41:17.690
2025-07-02 06:41:17.691 # pump out diffs from after the synch point
2025-07-02 06:41:17.691 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.691
2025-07-02 06:41:17.691 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.691 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.691
2025-07-02 06:41:17.691 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.691 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.691 alo = 273, ahi = 1101
2025-07-02 06:41:17.691 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.691 blo = 273, bhi = 1101
2025-07-02 06:41:17.691
2025-07-02 06:41:17.691 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.691 g = []
2025-07-02 06:41:17.691 if alo < ahi:
2025-07-02 06:41:17.691 if blo < bhi:
2025-07-02 06:41:17.691 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.691 else:
2025-07-02 06:41:17.691 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.692 elif blo < bhi:
2025-07-02 06:41:17.692 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 > yield from g
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.692 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.692 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.692 alo = 273, ahi = 1101
2025-07-02 06:41:17.692 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.692 blo = 273, bhi = 1101
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.692 r"""
2025-07-02 06:41:17.692 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.692 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.692 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.693 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.693
2025-07-02 06:41:17.693 Example:
2025-07-02 06:41:17.693
2025-07-02 06:41:17.693 >>> d = Differ()
2025-07-02 06:41:17.693 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.693 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.693 >>> print(''.join(results), end="")
2025-07-02 06:41:17.693 - abcDefghiJkl
2025-07-02 06:41:17.693 + abcdefGhijkl
2025-07-02 06:41:17.693 """
2025-07-02 06:41:17.693
2025-07-02 06:41:17.693 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.693 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.693 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.693 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.693 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.694
2025-07-02 06:41:17.694 # search for the pair that matches best without being identical
2025-07-02 06:41:17.694 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.694 # on junk -- unless we have to)
2025-07-02 06:41:17.694 for j in range(blo, bhi):
2025-07-02 06:41:17.694 bj = b[j]
2025-07-02 06:41:17.694 cruncher.set_seq2(bj)
2025-07-02 06:41:17.694 for i in range(alo, ahi):
2025-07-02 06:41:17.694 ai = a[i]
2025-07-02 06:41:17.694 if ai == bj:
2025-07-02 06:41:17.694 if eqi is None:
2025-07-02 06:41:17.694 eqi, eqj = i, j
2025-07-02 06:41:17.694 continue
2025-07-02 06:41:17.694 cruncher.set_seq1(ai)
2025-07-02 06:41:17.694 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.694 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.694 # compares by a factor of 3.
2025-07-02 06:41:17.694 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.694 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.694 # of the computation is cached by cruncher
2025-07-02 06:41:17.695 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.695 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.695 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.695 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.695 if best_ratio < cutoff:
2025-07-02 06:41:17.695 # no non-identical "pretty close" pair
2025-07-02 06:41:17.695 if eqi is None:
2025-07-02 06:41:17.695 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.695 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.695 return
2025-07-02 06:41:17.695 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.695 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.695 else:
2025-07-02 06:41:17.695 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.695 eqi = None
2025-07-02 06:41:17.695
2025-07-02 06:41:17.695 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.695 # identical
2025-07-02 06:41:17.695
2025-07-02 06:41:17.695 # pump out diffs from before the synch point
2025-07-02 06:41:17.696 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.696
2025-07-02 06:41:17.696 # do intraline marking on the synch pair
2025-07-02 06:41:17.696 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.696 if eqi is None:
2025-07-02 06:41:17.696 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.696 atags = btags = ""
2025-07-02 06:41:17.696 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.696 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.696 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.696 if tag == 'replace':
2025-07-02 06:41:17.696 atags += '^' * la
2025-07-02 06:41:17.696 btags += '^' * lb
2025-07-02 06:41:17.696 elif tag == 'delete':
2025-07-02 06:41:17.696 atags += '-' * la
2025-07-02 06:41:17.696 elif tag == 'insert':
2025-07-02 06:41:17.696 btags += '+' * lb
2025-07-02 06:41:17.696 elif tag == 'equal':
2025-07-02 06:41:17.696 atags += ' ' * la
2025-07-02 06:41:17.696 btags += ' ' * lb
2025-07-02 06:41:17.697 else:
2025-07-02 06:41:17.697 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.697 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.697 else:
2025-07-02 06:41:17.697 # the synch pair is identical
2025-07-02 06:41:17.697 yield ' ' + aelt
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697 # pump out diffs from after the synch point
2025-07-02 06:41:17.697 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.697 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.697 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.697 alo = 274, ahi = 1101
2025-07-02 06:41:17.697 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.697 blo = 274, bhi = 1101
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.698 g = []
2025-07-02 06:41:17.698 if alo < ahi:
2025-07-02 06:41:17.698 if blo < bhi:
2025-07-02 06:41:17.698 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.698 else:
2025-07-02 06:41:17.698 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.698 elif blo < bhi:
2025-07-02 06:41:17.698 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.698
2025-07-02 06:41:17.698 > yield from g
2025-07-02 06:41:17.698
2025-07-02 06:41:17.698 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.698 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.698
2025-07-02 06:41:17.698 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.698 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.698 alo = 274, ahi = 1101
2025-07-02 06:41:17.698 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.698 blo = 274, bhi = 1101
2025-07-02 06:41:17.698
2025-07-02 06:41:17.699 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.699 r"""
2025-07-02 06:41:17.699 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.699 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.699 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.699 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.699
2025-07-02 06:41:17.699 Example:
2025-07-02 06:41:17.699
2025-07-02 06:41:17.699 >>> d = Differ()
2025-07-02 06:41:17.699 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.699 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.699 >>> print(''.join(results), end="")
2025-07-02 06:41:17.699 - abcDefghiJkl
2025-07-02 06:41:17.699 + abcdefGhijkl
2025-07-02 06:41:17.699 """
2025-07-02 06:41:17.699
2025-07-02 06:41:17.699 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.700 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.700 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.700 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.700 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.700
2025-07-02 06:41:17.700 # search for the pair that matches best without being identical
2025-07-02 06:41:17.700 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.700 # on junk -- unless we have to)
2025-07-02 06:41:17.700 for j in range(blo, bhi):
2025-07-02 06:41:17.700 bj = b[j]
2025-07-02 06:41:17.700 cruncher.set_seq2(bj)
2025-07-02 06:41:17.700 for i in range(alo, ahi):
2025-07-02 06:41:17.700 ai = a[i]
2025-07-02 06:41:17.700 if ai == bj:
2025-07-02 06:41:17.700 if eqi is None:
2025-07-02 06:41:17.700 eqi, eqj = i, j
2025-07-02 06:41:17.700 continue
2025-07-02 06:41:17.700 cruncher.set_seq1(ai)
2025-07-02 06:41:17.700 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.701 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.701 # compares by a factor of 3.
2025-07-02 06:41:17.701 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.701 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.701 # of the computation is cached by cruncher
2025-07-02 06:41:17.701 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.701 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.701 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.701 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.701 if best_ratio < cutoff:
2025-07-02 06:41:17.701 # no non-identical "pretty close" pair
2025-07-02 06:41:17.701 if eqi is None:
2025-07-02 06:41:17.701 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.701 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.701 return
2025-07-02 06:41:17.701 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.701 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.701 else:
2025-07-02 06:41:17.701 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.702 eqi = None
2025-07-02 06:41:17.702
2025-07-02 06:41:17.702 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.702 # identical
2025-07-02 06:41:17.702
2025-07-02 06:41:17.702 # pump out diffs from before the synch point
2025-07-02 06:41:17.702 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.702
2025-07-02 06:41:17.702 # do intraline marking on the synch pair
2025-07-02 06:41:17.702 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.702 if eqi is None:
2025-07-02 06:41:17.702 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.702 atags = btags = ""
2025-07-02 06:41:17.702 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.702 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.702 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.702 if tag == 'replace':
2025-07-02 06:41:17.702 atags += '^' * la
2025-07-02 06:41:17.702 btags += '^' * lb
2025-07-02 06:41:17.703 elif tag == 'delete':
2025-07-02 06:41:17.703 atags += '-' * la
2025-07-02 06:41:17.703 elif tag == 'insert':
2025-07-02 06:41:17.703 btags += '+' * lb
2025-07-02 06:41:17.703 elif tag == 'equal':
2025-07-02 06:41:17.703 atags += ' ' * la
2025-07-02 06:41:17.703 btags += ' ' * lb
2025-07-02 06:41:17.703 else:
2025-07-02 06:41:17.703 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.703 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.703 else:
2025-07-02 06:41:17.703 # the synch pair is identical
2025-07-02 06:41:17.703 yield ' ' + aelt
2025-07-02 06:41:17.703
2025-07-02 06:41:17.703 # pump out diffs from after the synch point
2025-07-02 06:41:17.703 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.703
2025-07-02 06:41:17.703 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.703 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.703
2025-07-02 06:41:17.703 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.704 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.704 alo = 275, ahi = 1101
2025-07-02 06:41:17.704 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.704 blo = 275, bhi = 1101
2025-07-02 06:41:17.704
2025-07-02 06:41:17.704 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.704 g = []
2025-07-02 06:41:17.704 if alo < ahi:
2025-07-02 06:41:17.704 if blo < bhi:
2025-07-02 06:41:17.704 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.704 else:
2025-07-02 06:41:17.704 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.704 elif blo < bhi:
2025-07-02 06:41:17.704 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.704
2025-07-02 06:41:17.704 > yield from g
2025-07-02 06:41:17.704
2025-07-02 06:41:17.704 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.704 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.704
2025-07-02 06:41:17.705 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.705 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.705 alo = 275, ahi = 1101
2025-07-02 06:41:17.705 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.705 blo = 275, bhi = 1101
2025-07-02 06:41:17.705
2025-07-02 06:41:17.705 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.705 r"""
2025-07-02 06:41:17.705 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.705 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.705 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.705 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.705
2025-07-02 06:41:17.705 Example:
2025-07-02 06:41:17.705
2025-07-02 06:41:17.705 >>> d = Differ()
2025-07-02 06:41:17.705 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.705 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.705 >>> print(''.join(results), end="")
2025-07-02 06:41:17.705 - abcDefghiJkl
2025-07-02 06:41:17.706 + abcdefGhijkl
2025-07-02 06:41:17.706 """
2025-07-02 06:41:17.706
2025-07-02 06:41:17.706 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.706 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.706 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.706 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.706 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.706
2025-07-02 06:41:17.706 # search for the pair that matches best without being identical
2025-07-02 06:41:17.706 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.706 # on junk -- unless we have to)
2025-07-02 06:41:17.706 for j in range(blo, bhi):
2025-07-02 06:41:17.706 bj = b[j]
2025-07-02 06:41:17.706 cruncher.set_seq2(bj)
2025-07-02 06:41:17.706 for i in range(alo, ahi):
2025-07-02 06:41:17.706 ai = a[i]
2025-07-02 06:41:17.706 if ai == bj:
2025-07-02 06:41:17.707 if eqi is None:
2025-07-02 06:41:17.707 eqi, eqj = i, j
2025-07-02 06:41:17.707 continue
2025-07-02 06:41:17.707 cruncher.set_seq1(ai)
2025-07-02 06:41:17.707 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.707 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.707 # compares by a factor of 3.
2025-07-02 06:41:17.707 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.707 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.707 # of the computation is cached by cruncher
2025-07-02 06:41:17.707 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.707 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.707 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.707 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.707 if best_ratio < cutoff:
2025-07-02 06:41:17.707 # no non-identical "pretty close" pair
2025-07-02 06:41:17.707 if eqi is None:
2025-07-02 06:41:17.707 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.708 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.708 return
2025-07-02 06:41:17.708 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.708 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.708 else:
2025-07-02 06:41:17.708 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.708 eqi = None
2025-07-02 06:41:17.708
2025-07-02 06:41:17.708 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.708 # identical
2025-07-02 06:41:17.708
2025-07-02 06:41:17.708 # pump out diffs from before the synch point
2025-07-02 06:41:17.708 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.708
2025-07-02 06:41:17.708 # do intraline marking on the synch pair
2025-07-02 06:41:17.708 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.708 if eqi is None:
2025-07-02 06:41:17.708 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.708 atags = btags = ""
2025-07-02 06:41:17.708 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.709 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.709 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.709 if tag == 'replace':
2025-07-02 06:41:17.709 atags += '^' * la
2025-07-02 06:41:17.709 btags += '^' * lb
2025-07-02 06:41:17.709 elif tag == 'delete':
2025-07-02 06:41:17.709 atags += '-' * la
2025-07-02 06:41:17.709 elif tag == 'insert':
2025-07-02 06:41:17.709 btags += '+' * lb
2025-07-02 06:41:17.709 elif tag == 'equal':
2025-07-02 06:41:17.709 atags += ' ' * la
2025-07-02 06:41:17.709 btags += ' ' * lb
2025-07-02 06:41:17.709 else:
2025-07-02 06:41:17.709 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.709 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.709 else:
2025-07-02 06:41:17.709 # the synch pair is identical
2025-07-02 06:41:17.710 yield ' ' + aelt
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710 # pump out diffs from after the synch point
2025-07-02 06:41:17.710 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.710 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.710 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.710 alo = 276, ahi = 1101
2025-07-02 06:41:17.710 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.710 blo = 276, bhi = 1101
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.710 g = []
2025-07-02 06:41:17.710 if alo < ahi:
2025-07-02 06:41:17.710 if blo < bhi:
2025-07-02 06:41:17.710 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.711 else:
2025-07-02 06:41:17.711 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.711 elif blo < bhi:
2025-07-02 06:41:17.711 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 > yield from g
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.711 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.711 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.711 alo = 276, ahi = 1101
2025-07-02 06:41:17.711 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.711 blo = 276, bhi = 1101
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.711 r"""
2025-07-02 06:41:17.711 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.711 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.712 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.712 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.712
2025-07-02 06:41:17.712 Example:
2025-07-02 06:41:17.712
2025-07-02 06:41:17.712 >>> d = Differ()
2025-07-02 06:41:17.712 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.712 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.712 >>> print(''.join(results), end="")
2025-07-02 06:41:17.712 - abcDefghiJkl
2025-07-02 06:41:17.712 + abcdefGhijkl
2025-07-02 06:41:17.712 """
2025-07-02 06:41:17.712
2025-07-02 06:41:17.712 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.712 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.712 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.712 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.712 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.713
2025-07-02 06:41:17.713 # search for the pair that matches best without being identical
2025-07-02 06:41:17.713 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.713 # on junk -- unless we have to)
2025-07-02 06:41:17.713 for j in range(blo, bhi):
2025-07-02 06:41:17.713 bj = b[j]
2025-07-02 06:41:17.713 cruncher.set_seq2(bj)
2025-07-02 06:41:17.713 for i in range(alo, ahi):
2025-07-02 06:41:17.713 ai = a[i]
2025-07-02 06:41:17.713 if ai == bj:
2025-07-02 06:41:17.713 if eqi is None:
2025-07-02 06:41:17.713 eqi, eqj = i, j
2025-07-02 06:41:17.713 continue
2025-07-02 06:41:17.713 cruncher.set_seq1(ai)
2025-07-02 06:41:17.713 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.713 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.713 # compares by a factor of 3.
2025-07-02 06:41:17.713 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.713 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.713 # of the computation is cached by cruncher
2025-07-02 06:41:17.714 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.714 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.714 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.714 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.714 if best_ratio < cutoff:
2025-07-02 06:41:17.714 # no non-identical "pretty close" pair
2025-07-02 06:41:17.714 if eqi is None:
2025-07-02 06:41:17.714 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.714 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.714 return
2025-07-02 06:41:17.714 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.714 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.714 else:
2025-07-02 06:41:17.714 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.714 eqi = None
2025-07-02 06:41:17.714
2025-07-02 06:41:17.714 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.714 # identical
2025-07-02 06:41:17.714
2025-07-02 06:41:17.714 # pump out diffs from before the synch point
2025-07-02 06:41:17.715 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.715
2025-07-02 06:41:17.715 # do intraline marking on the synch pair
2025-07-02 06:41:17.715 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.715 if eqi is None:
2025-07-02 06:41:17.715 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.715 atags = btags = ""
2025-07-02 06:41:17.715 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.715 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.715 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.715 if tag == 'replace':
2025-07-02 06:41:17.715 atags += '^' * la
2025-07-02 06:41:17.715 btags += '^' * lb
2025-07-02 06:41:17.715 elif tag == 'delete':
2025-07-02 06:41:17.715 atags += '-' * la
2025-07-02 06:41:17.715 elif tag == 'insert':
2025-07-02 06:41:17.715 btags += '+' * lb
2025-07-02 06:41:17.715 elif tag == 'equal':
2025-07-02 06:41:17.715 atags += ' ' * la
2025-07-02 06:41:17.715 btags += ' ' * lb
2025-07-02 06:41:17.716 else:
2025-07-02 06:41:17.716 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.716 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.716 else:
2025-07-02 06:41:17.716 # the synch pair is identical
2025-07-02 06:41:17.716 yield ' ' + aelt
2025-07-02 06:41:17.716
2025-07-02 06:41:17.716 # pump out diffs from after the synch point
2025-07-02 06:41:17.716 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.716
2025-07-02 06:41:17.716 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.716 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.716
2025-07-02 06:41:17.716 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.716 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.716 alo = 277, ahi = 1101
2025-07-02 06:41:17.716 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.717 blo = 277, bhi = 1101
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.717 g = []
2025-07-02 06:41:17.717 if alo < ahi:
2025-07-02 06:41:17.717 if blo < bhi:
2025-07-02 06:41:17.717 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.717 else:
2025-07-02 06:41:17.717 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.717 elif blo < bhi:
2025-07-02 06:41:17.717 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 > yield from g
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.717 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.717 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.718 alo = 277, ahi = 1101
2025-07-02 06:41:17.718 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.718 blo = 277, bhi = 1101
2025-07-02 06:41:17.718
2025-07-02 06:41:17.718 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.718 r"""
2025-07-02 06:41:17.718 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.718 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.718 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.718 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.718
2025-07-02 06:41:17.718 Example:
2025-07-02 06:41:17.718
2025-07-02 06:41:17.718 >>> d = Differ()
2025-07-02 06:41:17.718 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.718 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.718 >>> print(''.join(results), end="")
2025-07-02 06:41:17.719 - abcDefghiJkl
2025-07-02 06:41:17.719 + abcdefGhijkl
2025-07-02 06:41:17.719 """
2025-07-02 06:41:17.719
2025-07-02 06:41:17.719 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.719 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.719 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.719 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.719 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.719
2025-07-02 06:41:17.719 # search for the pair that matches best without being identical
2025-07-02 06:41:17.719 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.719 # on junk -- unless we have to)
2025-07-02 06:41:17.719 for j in range(blo, bhi):
2025-07-02 06:41:17.719 bj = b[j]
2025-07-02 06:41:17.719 cruncher.set_seq2(bj)
2025-07-02 06:41:17.719 for i in range(alo, ahi):
2025-07-02 06:41:17.719 ai = a[i]
2025-07-02 06:41:17.720 if ai == bj:
2025-07-02 06:41:17.720 if eqi is None:
2025-07-02 06:41:17.720 eqi, eqj = i, j
2025-07-02 06:41:17.720 continue
2025-07-02 06:41:17.720 cruncher.set_seq1(ai)
2025-07-02 06:41:17.720 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.720 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.720 # compares by a factor of 3.
2025-07-02 06:41:17.720 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.720 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.720 # of the computation is cached by cruncher
2025-07-02 06:41:17.720 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.720 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.720 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.720 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.720 if best_ratio < cutoff:
2025-07-02 06:41:17.720 # no non-identical "pretty close" pair
2025-07-02 06:41:17.720 if eqi is None:
2025-07-02 06:41:17.720 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.720 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.721 return
2025-07-02 06:41:17.721 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.721 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.721 else:
2025-07-02 06:41:17.721 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.721 eqi = None
2025-07-02 06:41:17.721
2025-07-02 06:41:17.721 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.721 # identical
2025-07-02 06:41:17.721
2025-07-02 06:41:17.721 # pump out diffs from before the synch point
2025-07-02 06:41:17.721 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.721
2025-07-02 06:41:17.721 # do intraline marking on the synch pair
2025-07-02 06:41:17.721 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.721 if eqi is None:
2025-07-02 06:41:17.721 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.721 atags = btags = ""
2025-07-02 06:41:17.722 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.722 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.722 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.722 if tag == 'replace':
2025-07-02 06:41:17.722 atags += '^' * la
2025-07-02 06:41:17.722 btags += '^' * lb
2025-07-02 06:41:17.722 elif tag == 'delete':
2025-07-02 06:41:17.722 atags += '-' * la
2025-07-02 06:41:17.722 elif tag == 'insert':
2025-07-02 06:41:17.722 btags += '+' * lb
2025-07-02 06:41:17.722 elif tag == 'equal':
2025-07-02 06:41:17.722 atags += ' ' * la
2025-07-02 06:41:17.722 btags += ' ' * lb
2025-07-02 06:41:17.722 else:
2025-07-02 06:41:17.722 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.722 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.722 else:
2025-07-02 06:41:17.722 # the synch pair is identical
2025-07-02 06:41:17.722 yield ' ' + aelt
2025-07-02 06:41:17.722
2025-07-02 06:41:17.723 # pump out diffs from after the synch point
2025-07-02 06:41:17.723 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.723
2025-07-02 06:41:17.723 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.723 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.723
2025-07-02 06:41:17.723 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.723 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.723 alo = 278, ahi = 1101
2025-07-02 06:41:17.723 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.723 blo = 278, bhi = 1101
2025-07-02 06:41:17.723
2025-07-02 06:41:17.723 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.723 g = []
2025-07-02 06:41:17.723 if alo < ahi:
2025-07-02 06:41:17.723 if blo < bhi:
2025-07-02 06:41:17.723 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.723 else:
2025-07-02 06:41:17.723 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.723 elif blo < bhi:
2025-07-02 06:41:17.724 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 > yield from g
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.724 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.724 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.724 alo = 278, ahi = 1101
2025-07-02 06:41:17.724 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.724 blo = 278, bhi = 1101
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.724 r"""
2025-07-02 06:41:17.724 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.724 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.724 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.724 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.724
2025-07-02 06:41:17.725 Example:
2025-07-02 06:41:17.725
2025-07-02 06:41:17.725 >>> d = Differ()
2025-07-02 06:41:17.725 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.725 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.725 >>> print(''.join(results), end="")
2025-07-02 06:41:17.725 - abcDefghiJkl
2025-07-02 06:41:17.725 + abcdefGhijkl
2025-07-02 06:41:17.725 """
2025-07-02 06:41:17.725
2025-07-02 06:41:17.725 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.725 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.725 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.725 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.725 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.725
2025-07-02 06:41:17.726 # search for the pair that matches best without being identical
2025-07-02 06:41:17.726 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.726 # on junk -- unless we have to)
2025-07-02 06:41:17.726 for j in range(blo, bhi):
2025-07-02 06:41:17.726 bj = b[j]
2025-07-02 06:41:17.726 cruncher.set_seq2(bj)
2025-07-02 06:41:17.726 for i in range(alo, ahi):
2025-07-02 06:41:17.726 ai = a[i]
2025-07-02 06:41:17.726 if ai == bj:
2025-07-02 06:41:17.726 if eqi is None:
2025-07-02 06:41:17.726 eqi, eqj = i, j
2025-07-02 06:41:17.726 continue
2025-07-02 06:41:17.726 cruncher.set_seq1(ai)
2025-07-02 06:41:17.726 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.726 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.726 # compares by a factor of 3.
2025-07-02 06:41:17.726 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.726 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.726 # of the computation is cached by cruncher
2025-07-02 06:41:17.726 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.727 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.727 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.727 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.727 if best_ratio < cutoff:
2025-07-02 06:41:17.727 # no non-identical "pretty close" pair
2025-07-02 06:41:17.727 if eqi is None:
2025-07-02 06:41:17.727 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.727 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.727 return
2025-07-02 06:41:17.727 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.727 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.727 else:
2025-07-02 06:41:17.727 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.727 eqi = None
2025-07-02 06:41:17.727
2025-07-02 06:41:17.727 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.727 # identical
2025-07-02 06:41:17.727
2025-07-02 06:41:17.728 # pump out diffs from before the synch point
2025-07-02 06:41:17.728 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.728
2025-07-02 06:41:17.728 # do intraline marking on the synch pair
2025-07-02 06:41:17.728 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.728 if eqi is None:
2025-07-02 06:41:17.728 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.728 atags = btags = ""
2025-07-02 06:41:17.728 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.728 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.728 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.728 if tag == 'replace':
2025-07-02 06:41:17.728 atags += '^' * la
2025-07-02 06:41:17.728 btags += '^' * lb
2025-07-02 06:41:17.728 elif tag == 'delete':
2025-07-02 06:41:17.728 atags += '-' * la
2025-07-02 06:41:17.728 elif tag == 'insert':
2025-07-02 06:41:17.728 btags += '+' * lb
2025-07-02 06:41:17.728 elif tag == 'equal':
2025-07-02 06:41:17.729 atags += ' ' * la
2025-07-02 06:41:17.729 btags += ' ' * lb
2025-07-02 06:41:17.729 else:
2025-07-02 06:41:17.729 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.729 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.729 else:
2025-07-02 06:41:17.729 # the synch pair is identical
2025-07-02 06:41:17.729 yield ' ' + aelt
2025-07-02 06:41:17.729
2025-07-02 06:41:17.729 # pump out diffs from after the synch point
2025-07-02 06:41:17.729 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.729
2025-07-02 06:41:17.729 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.729 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.729
2025-07-02 06:41:17.729 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.729 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.729 alo = 279, ahi = 1101
2025-07-02 06:41:17.729 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.729 blo = 279, bhi = 1101
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.730 g = []
2025-07-02 06:41:17.730 if alo < ahi:
2025-07-02 06:41:17.730 if blo < bhi:
2025-07-02 06:41:17.730 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.730 else:
2025-07-02 06:41:17.730 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.730 elif blo < bhi:
2025-07-02 06:41:17.730 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 > yield from g
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.730 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.730 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.730 alo = 279, ahi = 1101
2025-07-02 06:41:17.730 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.731 blo = 279, bhi = 1101
2025-07-02 06:41:17.731
2025-07-02 06:41:17.731 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.731 r"""
2025-07-02 06:41:17.731 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.731 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.731 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.731 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.731
2025-07-02 06:41:17.731 Example:
2025-07-02 06:41:17.731
2025-07-02 06:41:17.731 >>> d = Differ()
2025-07-02 06:41:17.731 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.731 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.731 >>> print(''.join(results), end="")
2025-07-02 06:41:17.731 - abcDefghiJkl
2025-07-02 06:41:17.731 + abcdefGhijkl
2025-07-02 06:41:17.731 """
2025-07-02 06:41:17.732
2025-07-02 06:41:17.732 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.732 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.732 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.732 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.732 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.732
2025-07-02 06:41:17.732 # search for the pair that matches best without being identical
2025-07-02 06:41:17.732 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.732 # on junk -- unless we have to)
2025-07-02 06:41:17.732 for j in range(blo, bhi):
2025-07-02 06:41:17.732 bj = b[j]
2025-07-02 06:41:17.732 cruncher.set_seq2(bj)
2025-07-02 06:41:17.732 for i in range(alo, ahi):
2025-07-02 06:41:17.732 ai = a[i]
2025-07-02 06:41:17.732 if ai == bj:
2025-07-02 06:41:17.732 if eqi is None:
2025-07-02 06:41:17.732 eqi, eqj = i, j
2025-07-02 06:41:17.732 continue
2025-07-02 06:41:17.732 cruncher.set_seq1(ai)
2025-07-02 06:41:17.732 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.733 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.733 # compares by a factor of 3.
2025-07-02 06:41:17.733 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.733 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.733 # of the computation is cached by cruncher
2025-07-02 06:41:17.733 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.733 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.733 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.733 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.733 if best_ratio < cutoff:
2025-07-02 06:41:17.733 # no non-identical "pretty close" pair
2025-07-02 06:41:17.733 if eqi is None:
2025-07-02 06:41:17.733 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.733 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.733 return
2025-07-02 06:41:17.733 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.733 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.733 else:
2025-07-02 06:41:17.733 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.733 eqi = None
2025-07-02 06:41:17.734
2025-07-02 06:41:17.734 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.734 # identical
2025-07-02 06:41:17.734
2025-07-02 06:41:17.734 # pump out diffs from before the synch point
2025-07-02 06:41:17.734 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.734
2025-07-02 06:41:17.734 # do intraline marking on the synch pair
2025-07-02 06:41:17.734 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.734 if eqi is None:
2025-07-02 06:41:17.734 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.734 atags = btags = ""
2025-07-02 06:41:17.734 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.734 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.734 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.734 if tag == 'replace':
2025-07-02 06:41:17.734 atags += '^' * la
2025-07-02 06:41:17.734 btags += '^' * lb
2025-07-02 06:41:17.734 elif tag == 'delete':
2025-07-02 06:41:17.734 atags += '-' * la
2025-07-02 06:41:17.735 elif tag == 'insert':
2025-07-02 06:41:17.735 btags += '+' * lb
2025-07-02 06:41:17.735 elif tag == 'equal':
2025-07-02 06:41:17.735 atags += ' ' * la
2025-07-02 06:41:17.735 btags += ' ' * lb
2025-07-02 06:41:17.735 else:
2025-07-02 06:41:17.735 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.735 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.735 else:
2025-07-02 06:41:17.735 # the synch pair is identical
2025-07-02 06:41:17.735 yield ' ' + aelt
2025-07-02 06:41:17.735
2025-07-02 06:41:17.735 # pump out diffs from after the synch point
2025-07-02 06:41:17.735 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.735
2025-07-02 06:41:17.735 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.735 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.735
2025-07-02 06:41:17.735 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.735 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.736 alo = 280, ahi = 1101
2025-07-02 06:41:17.736 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.736 blo = 280, bhi = 1101
2025-07-02 06:41:17.736
2025-07-02 06:41:17.736 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.736 g = []
2025-07-02 06:41:17.736 if alo < ahi:
2025-07-02 06:41:17.736 if blo < bhi:
2025-07-02 06:41:17.736 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.736 else:
2025-07-02 06:41:17.736 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.736 elif blo < bhi:
2025-07-02 06:41:17.736 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.736
2025-07-02 06:41:17.736 > yield from g
2025-07-02 06:41:17.736
2025-07-02 06:41:17.736 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.736 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.737 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.737 alo = 280, ahi = 1101
2025-07-02 06:41:17.737 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.737 blo = 280, bhi = 1101
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.737 r"""
2025-07-02 06:41:17.737 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.737 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.737 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.737 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737 Example:
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737 >>> d = Differ()
2025-07-02 06:41:17.737 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.737 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.738 >>> print(''.join(results), end="")
2025-07-02 06:41:17.738 - abcDefghiJkl
2025-07-02 06:41:17.738 + abcdefGhijkl
2025-07-02 06:41:17.738 """
2025-07-02 06:41:17.738
2025-07-02 06:41:17.738 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.738 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.738 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.738 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.738 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.738
2025-07-02 06:41:17.738 # search for the pair that matches best without being identical
2025-07-02 06:41:17.738 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.738 # on junk -- unless we have to)
2025-07-02 06:41:17.738 for j in range(blo, bhi):
2025-07-02 06:41:17.738 bj = b[j]
2025-07-02 06:41:17.738 cruncher.set_seq2(bj)
2025-07-02 06:41:17.738 for i in range(alo, ahi):
2025-07-02 06:41:17.739 ai = a[i]
2025-07-02 06:41:17.739 if ai == bj:
2025-07-02 06:41:17.739 if eqi is None:
2025-07-02 06:41:17.739 eqi, eqj = i, j
2025-07-02 06:41:17.739 continue
2025-07-02 06:41:17.739 cruncher.set_seq1(ai)
2025-07-02 06:41:17.739 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.739 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.739 # compares by a factor of 3.
2025-07-02 06:41:17.739 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.739 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.739 # of the computation is cached by cruncher
2025-07-02 06:41:17.739 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.739 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.739 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.739 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.739 if best_ratio < cutoff:
2025-07-02 06:41:17.739 # no non-identical "pretty close" pair
2025-07-02 06:41:17.739 if eqi is None:
2025-07-02 06:41:17.739 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.739 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.740 return
2025-07-02 06:41:17.740 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.740 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.740 else:
2025-07-02 06:41:17.740 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.740 eqi = None
2025-07-02 06:41:17.740
2025-07-02 06:41:17.740 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.740 # identical
2025-07-02 06:41:17.740
2025-07-02 06:41:17.740 # pump out diffs from before the synch point
2025-07-02 06:41:17.740 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.740
2025-07-02 06:41:17.740 # do intraline marking on the synch pair
2025-07-02 06:41:17.740 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.740 if eqi is None:
2025-07-02 06:41:17.740 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.740 atags = btags = ""
2025-07-02 06:41:17.740 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.740 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.741 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.741 if tag == 'replace':
2025-07-02 06:41:17.741 atags += '^' * la
2025-07-02 06:41:17.741 btags += '^' * lb
2025-07-02 06:41:17.741 elif tag == 'delete':
2025-07-02 06:41:17.741 atags += '-' * la
2025-07-02 06:41:17.741 elif tag == 'insert':
2025-07-02 06:41:17.741 btags += '+' * lb
2025-07-02 06:41:17.741 elif tag == 'equal':
2025-07-02 06:41:17.741 atags += ' ' * la
2025-07-02 06:41:17.741 btags += ' ' * lb
2025-07-02 06:41:17.741 else:
2025-07-02 06:41:17.741 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.741 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.741 else:
2025-07-02 06:41:17.741 # the synch pair is identical
2025-07-02 06:41:17.741 yield ' ' + aelt
2025-07-02 06:41:17.741
2025-07-02 06:41:17.742 # pump out diffs from after the synch point
2025-07-02 06:41:17.742 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.742
2025-07-02 06:41:17.742 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.742 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.742
2025-07-02 06:41:17.742 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.742 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.742 alo = 281, ahi = 1101
2025-07-02 06:41:17.742 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.742 blo = 281, bhi = 1101
2025-07-02 06:41:17.742
2025-07-02 06:41:17.742 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.742 g = []
2025-07-02 06:41:17.742 if alo < ahi:
2025-07-02 06:41:17.742 if blo < bhi:
2025-07-02 06:41:17.742 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.742 else:
2025-07-02 06:41:17.742 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.742 elif blo < bhi:
2025-07-02 06:41:17.743 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 > yield from g
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.743 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.743 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.743 alo = 281, ahi = 1101
2025-07-02 06:41:17.743 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.743 blo = 281, bhi = 1101
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.743 r"""
2025-07-02 06:41:17.743 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.743 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.743 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.743 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.743
2025-07-02 06:41:17.744 Example:
2025-07-02 06:41:17.744
2025-07-02 06:41:17.744 >>> d = Differ()
2025-07-02 06:41:17.744 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.744 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.744 >>> print(''.join(results), end="")
2025-07-02 06:41:17.744 - abcDefghiJkl
2025-07-02 06:41:17.744 + abcdefGhijkl
2025-07-02 06:41:17.744 """
2025-07-02 06:41:17.744
2025-07-02 06:41:17.744 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.744 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.744 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.744 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.744 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.744
2025-07-02 06:41:17.745 # search for the pair that matches best without being identical
2025-07-02 06:41:17.745 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.745 # on junk -- unless we have to)
2025-07-02 06:41:17.745 for j in range(blo, bhi):
2025-07-02 06:41:17.745 bj = b[j]
2025-07-02 06:41:17.745 cruncher.set_seq2(bj)
2025-07-02 06:41:17.745 for i in range(alo, ahi):
2025-07-02 06:41:17.745 ai = a[i]
2025-07-02 06:41:17.745 if ai == bj:
2025-07-02 06:41:17.745 if eqi is None:
2025-07-02 06:41:17.745 eqi, eqj = i, j
2025-07-02 06:41:17.745 continue
2025-07-02 06:41:17.745 cruncher.set_seq1(ai)
2025-07-02 06:41:17.745 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.745 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.745 # compares by a factor of 3.
2025-07-02 06:41:17.745 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.745 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.745 # of the computation is cached by cruncher
2025-07-02 06:41:17.745 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.746 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.746 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.746 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.746 if best_ratio < cutoff:
2025-07-02 06:41:17.746 # no non-identical "pretty close" pair
2025-07-02 06:41:17.746 if eqi is None:
2025-07-02 06:41:17.746 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.746 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.746 return
2025-07-02 06:41:17.746 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.746 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.746 else:
2025-07-02 06:41:17.746 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.746 eqi = None
2025-07-02 06:41:17.746
2025-07-02 06:41:17.746 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.746 # identical
2025-07-02 06:41:17.746
2025-07-02 06:41:17.746 # pump out diffs from before the synch point
2025-07-02 06:41:17.747 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.747
2025-07-02 06:41:17.747 # do intraline marking on the synch pair
2025-07-02 06:41:17.747 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.747 if eqi is None:
2025-07-02 06:41:17.747 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.747 atags = btags = ""
2025-07-02 06:41:17.747 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.747 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.747 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.747 if tag == 'replace':
2025-07-02 06:41:17.747 atags += '^' * la
2025-07-02 06:41:17.747 btags += '^' * lb
2025-07-02 06:41:17.747 elif tag == 'delete':
2025-07-02 06:41:17.747 atags += '-' * la
2025-07-02 06:41:17.747 elif tag == 'insert':
2025-07-02 06:41:17.747 btags += '+' * lb
2025-07-02 06:41:17.747 elif tag == 'equal':
2025-07-02 06:41:17.747 atags += ' ' * la
2025-07-02 06:41:17.747 btags += ' ' * lb
2025-07-02 06:41:17.747 else:
2025-07-02 06:41:17.748 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.748 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.748 else:
2025-07-02 06:41:17.748 # the synch pair is identical
2025-07-02 06:41:17.748 yield ' ' + aelt
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748 # pump out diffs from after the synch point
2025-07-02 06:41:17.748 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.748 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.748 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.748 alo = 282, ahi = 1101
2025-07-02 06:41:17.748 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.748 blo = 282, bhi = 1101
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.748 g = []
2025-07-02 06:41:17.749 if alo < ahi:
2025-07-02 06:41:17.749 if blo < bhi:
2025-07-02 06:41:17.749 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.749 else:
2025-07-02 06:41:17.749 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.749 elif blo < bhi:
2025-07-02 06:41:17.749 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 > yield from g
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.749 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.749 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.749 alo = 282, ahi = 1101
2025-07-02 06:41:17.749 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.749 blo = 282, bhi = 1101
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.750 r"""
2025-07-02 06:41:17.750 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.750 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.750 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.750 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.750
2025-07-02 06:41:17.750 Example:
2025-07-02 06:41:17.750
2025-07-02 06:41:17.750 >>> d = Differ()
2025-07-02 06:41:17.750 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.750 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.750 >>> print(''.join(results), end="")
2025-07-02 06:41:17.750 - abcDefghiJkl
2025-07-02 06:41:17.750 + abcdefGhijkl
2025-07-02 06:41:17.750 """
2025-07-02 06:41:17.750
2025-07-02 06:41:17.750 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.750 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.751 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.751 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.751 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.751
2025-07-02 06:41:17.751 # search for the pair that matches best without being identical
2025-07-02 06:41:17.751 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.751 # on junk -- unless we have to)
2025-07-02 06:41:17.751 for j in range(blo, bhi):
2025-07-02 06:41:17.751 bj = b[j]
2025-07-02 06:41:17.751 cruncher.set_seq2(bj)
2025-07-02 06:41:17.751 for i in range(alo, ahi):
2025-07-02 06:41:17.751 ai = a[i]
2025-07-02 06:41:17.751 if ai == bj:
2025-07-02 06:41:17.751 if eqi is None:
2025-07-02 06:41:17.751 eqi, eqj = i, j
2025-07-02 06:41:17.751 continue
2025-07-02 06:41:17.751 cruncher.set_seq1(ai)
2025-07-02 06:41:17.751 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.751 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.751 # compares by a factor of 3.
2025-07-02 06:41:17.751 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.752 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.752 # of the computation is cached by cruncher
2025-07-02 06:41:17.752 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.752 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.752 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.752 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.752 if best_ratio < cutoff:
2025-07-02 06:41:17.752 # no non-identical "pretty close" pair
2025-07-02 06:41:17.752 if eqi is None:
2025-07-02 06:41:17.752 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.752 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.752 return
2025-07-02 06:41:17.752 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.752 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.752 else:
2025-07-02 06:41:17.752 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.752 eqi = None
2025-07-02 06:41:17.752
2025-07-02 06:41:17.752 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.752 # identical
2025-07-02 06:41:17.753
2025-07-02 06:41:17.753 # pump out diffs from before the synch point
2025-07-02 06:41:17.753 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.753
2025-07-02 06:41:17.753 # do intraline marking on the synch pair
2025-07-02 06:41:17.753 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.753 if eqi is None:
2025-07-02 06:41:17.753 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.753 atags = btags = ""
2025-07-02 06:41:17.753 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.753 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.753 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.753 if tag == 'replace':
2025-07-02 06:41:17.753 atags += '^' * la
2025-07-02 06:41:17.753 btags += '^' * lb
2025-07-02 06:41:17.753 elif tag == 'delete':
2025-07-02 06:41:17.753 atags += '-' * la
2025-07-02 06:41:17.753 elif tag == 'insert':
2025-07-02 06:41:17.753 btags += '+' * lb
2025-07-02 06:41:17.754 elif tag == 'equal':
2025-07-02 06:41:17.754 atags += ' ' * la
2025-07-02 06:41:17.754 btags += ' ' * lb
2025-07-02 06:41:17.754 else:
2025-07-02 06:41:17.754 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.754 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.754 else:
2025-07-02 06:41:17.754 # the synch pair is identical
2025-07-02 06:41:17.754 yield ' ' + aelt
2025-07-02 06:41:17.754
2025-07-02 06:41:17.754 # pump out diffs from after the synch point
2025-07-02 06:41:17.754 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.754
2025-07-02 06:41:17.754 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.754 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.754
2025-07-02 06:41:17.754 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.754 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.754 alo = 283, ahi = 1101
2025-07-02 06:41:17.755 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.755 blo = 283, bhi = 1101
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.755 g = []
2025-07-02 06:41:17.755 if alo < ahi:
2025-07-02 06:41:17.755 if blo < bhi:
2025-07-02 06:41:17.755 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.755 else:
2025-07-02 06:41:17.755 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.755 elif blo < bhi:
2025-07-02 06:41:17.755 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 > yield from g
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.755 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.755 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.756 alo = 283, ahi = 1101
2025-07-02 06:41:17.756 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.756 blo = 283, bhi = 1101
2025-07-02 06:41:17.756
2025-07-02 06:41:17.756 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.756 r"""
2025-07-02 06:41:17.756 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.756 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.756 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.756 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.756
2025-07-02 06:41:17.756 Example:
2025-07-02 06:41:17.756
2025-07-02 06:41:17.756 >>> d = Differ()
2025-07-02 06:41:17.756 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.756 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.756 >>> print(''.join(results), end="")
2025-07-02 06:41:17.756 - abcDefghiJkl
2025-07-02 06:41:17.756 + abcdefGhijkl
2025-07-02 06:41:17.757 """
2025-07-02 06:41:17.757
2025-07-02 06:41:17.757 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.757 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.757 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.757 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.757 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.757
2025-07-02 06:41:17.757 # search for the pair that matches best without being identical
2025-07-02 06:41:17.757 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.757 # on junk -- unless we have to)
2025-07-02 06:41:17.757 for j in range(blo, bhi):
2025-07-02 06:41:17.757 bj = b[j]
2025-07-02 06:41:17.757 cruncher.set_seq2(bj)
2025-07-02 06:41:17.757 for i in range(alo, ahi):
2025-07-02 06:41:17.757 ai = a[i]
2025-07-02 06:41:17.757 if ai == bj:
2025-07-02 06:41:17.757 if eqi is None:
2025-07-02 06:41:17.758 eqi, eqj = i, j
2025-07-02 06:41:17.758 continue
2025-07-02 06:41:17.758 cruncher.set_seq1(ai)
2025-07-02 06:41:17.758 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.758 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.758 # compares by a factor of 3.
2025-07-02 06:41:17.758 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.758 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.758 # of the computation is cached by cruncher
2025-07-02 06:41:17.758 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.758 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.758 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.758 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.758 if best_ratio < cutoff:
2025-07-02 06:41:17.758 # no non-identical "pretty close" pair
2025-07-02 06:41:17.758 if eqi is None:
2025-07-02 06:41:17.758 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.758 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.758 return
2025-07-02 06:41:17.759 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.759 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.759 else:
2025-07-02 06:41:17.759 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.759 eqi = None
2025-07-02 06:41:17.759
2025-07-02 06:41:17.759 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.759 # identical
2025-07-02 06:41:17.759
2025-07-02 06:41:17.759 # pump out diffs from before the synch point
2025-07-02 06:41:17.759 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.759
2025-07-02 06:41:17.759 # do intraline marking on the synch pair
2025-07-02 06:41:17.759 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.759 if eqi is None:
2025-07-02 06:41:17.759 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.759 atags = btags = ""
2025-07-02 06:41:17.759 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.759 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.759 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.760 if tag == 'replace':
2025-07-02 06:41:17.760 atags += '^' * la
2025-07-02 06:41:17.760 btags += '^' * lb
2025-07-02 06:41:17.760 elif tag == 'delete':
2025-07-02 06:41:17.760 atags += '-' * la
2025-07-02 06:41:17.760 elif tag == 'insert':
2025-07-02 06:41:17.760 btags += '+' * lb
2025-07-02 06:41:17.760 elif tag == 'equal':
2025-07-02 06:41:17.760 atags += ' ' * la
2025-07-02 06:41:17.760 btags += ' ' * lb
2025-07-02 06:41:17.760 else:
2025-07-02 06:41:17.760 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.760 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.760 else:
2025-07-02 06:41:17.760 # the synch pair is identical
2025-07-02 06:41:17.760 yield ' ' + aelt
2025-07-02 06:41:17.760
2025-07-02 06:41:17.760 # pump out diffs from after the synch point
2025-07-02 06:41:17.760 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.760
2025-07-02 06:41:17.761 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.761 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.761
2025-07-02 06:41:17.761 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.761 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.761 alo = 284, ahi = 1101
2025-07-02 06:41:17.761 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.761 blo = 284, bhi = 1101
2025-07-02 06:41:17.761
2025-07-02 06:41:17.761 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.761 g = []
2025-07-02 06:41:17.761 if alo < ahi:
2025-07-02 06:41:17.761 if blo < bhi:
2025-07-02 06:41:17.761 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.761 else:
2025-07-02 06:41:17.761 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.761 elif blo < bhi:
2025-07-02 06:41:17.761 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.761
2025-07-02 06:41:17.761 > yield from g
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.762 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.762 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.762 alo = 284, ahi = 1101
2025-07-02 06:41:17.762 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.762 blo = 284, bhi = 1101
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.762 r"""
2025-07-02 06:41:17.762 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.762 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.762 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.762 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762 Example:
2025-07-02 06:41:17.763
2025-07-02 06:41:17.763 >>> d = Differ()
2025-07-02 06:41:17.763 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.763 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.763 >>> print(''.join(results), end="")
2025-07-02 06:41:17.763 - abcDefghiJkl
2025-07-02 06:41:17.763 + abcdefGhijkl
2025-07-02 06:41:17.763 """
2025-07-02 06:41:17.763
2025-07-02 06:41:17.763 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.763 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.763 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.763 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.763 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.763
2025-07-02 06:41:17.763 # search for the pair that matches best without being identical
2025-07-02 06:41:17.763 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.764 # on junk -- unless we have to)
2025-07-02 06:41:17.764 for j in range(blo, bhi):
2025-07-02 06:41:17.764 bj = b[j]
2025-07-02 06:41:17.764 cruncher.set_seq2(bj)
2025-07-02 06:41:17.764 for i in range(alo, ahi):
2025-07-02 06:41:17.764 ai = a[i]
2025-07-02 06:41:17.764 if ai == bj:
2025-07-02 06:41:17.764 if eqi is None:
2025-07-02 06:41:17.764 eqi, eqj = i, j
2025-07-02 06:41:17.764 continue
2025-07-02 06:41:17.764 cruncher.set_seq1(ai)
2025-07-02 06:41:17.764 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.764 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.764 # compares by a factor of 3.
2025-07-02 06:41:17.764 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.764 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.764 # of the computation is cached by cruncher
2025-07-02 06:41:17.764 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.764 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.764 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.765 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.765 if best_ratio < cutoff:
2025-07-02 06:41:17.765 # no non-identical "pretty close" pair
2025-07-02 06:41:17.765 if eqi is None:
2025-07-02 06:41:17.765 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.765 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.765 return
2025-07-02 06:41:17.765 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.765 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.765 else:
2025-07-02 06:41:17.765 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.765 eqi = None
2025-07-02 06:41:17.765
2025-07-02 06:41:17.765 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.765 # identical
2025-07-02 06:41:17.765
2025-07-02 06:41:17.765 # pump out diffs from before the synch point
2025-07-02 06:41:17.765 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.765
2025-07-02 06:41:17.765 # do intraline marking on the synch pair
2025-07-02 06:41:17.765 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.766 if eqi is None:
2025-07-02 06:41:17.766 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.766 atags = btags = ""
2025-07-02 06:41:17.766 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.766 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.766 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.766 if tag == 'replace':
2025-07-02 06:41:17.766 atags += '^' * la
2025-07-02 06:41:17.766 btags += '^' * lb
2025-07-02 06:41:17.766 elif tag == 'delete':
2025-07-02 06:41:17.766 atags += '-' * la
2025-07-02 06:41:17.766 elif tag == 'insert':
2025-07-02 06:41:17.766 btags += '+' * lb
2025-07-02 06:41:17.766 elif tag == 'equal':
2025-07-02 06:41:17.766 atags += ' ' * la
2025-07-02 06:41:17.766 btags += ' ' * lb
2025-07-02 06:41:17.766 else:
2025-07-02 06:41:17.766 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.766 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.766 else:
2025-07-02 06:41:17.767 # the synch pair is identical
2025-07-02 06:41:17.767 yield ' ' + aelt
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767 # pump out diffs from after the synch point
2025-07-02 06:41:17.767 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.767 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.767 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.767 alo = 285, ahi = 1101
2025-07-02 06:41:17.767 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.767 blo = 285, bhi = 1101
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.767 g = []
2025-07-02 06:41:17.767 if alo < ahi:
2025-07-02 06:41:17.767 if blo < bhi:
2025-07-02 06:41:17.767 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.768 else:
2025-07-02 06:41:17.768 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.768 elif blo < bhi:
2025-07-02 06:41:17.768 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 > yield from g
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.768 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.768 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.768 alo = 285, ahi = 1101
2025-07-02 06:41:17.768 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.768 blo = 285, bhi = 1101
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.768 r"""
2025-07-02 06:41:17.768 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.768 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.769 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.769 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.769
2025-07-02 06:41:17.769 Example:
2025-07-02 06:41:17.769
2025-07-02 06:41:17.769 >>> d = Differ()
2025-07-02 06:41:17.769 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.769 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.769 >>> print(''.join(results), end="")
2025-07-02 06:41:17.769 - abcDefghiJkl
2025-07-02 06:41:17.769 + abcdefGhijkl
2025-07-02 06:41:17.769 """
2025-07-02 06:41:17.769
2025-07-02 06:41:17.769 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.769 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.769 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.769 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.769 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.770
2025-07-02 06:41:17.770 # search for the pair that matches best without being identical
2025-07-02 06:41:17.770 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.770 # on junk -- unless we have to)
2025-07-02 06:41:17.770 for j in range(blo, bhi):
2025-07-02 06:41:17.770 bj = b[j]
2025-07-02 06:41:17.770 cruncher.set_seq2(bj)
2025-07-02 06:41:17.770 for i in range(alo, ahi):
2025-07-02 06:41:17.770 ai = a[i]
2025-07-02 06:41:17.770 if ai == bj:
2025-07-02 06:41:17.770 if eqi is None:
2025-07-02 06:41:17.770 eqi, eqj = i, j
2025-07-02 06:41:17.770 continue
2025-07-02 06:41:17.770 cruncher.set_seq1(ai)
2025-07-02 06:41:17.770 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.770 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.770 # compares by a factor of 3.
2025-07-02 06:41:17.770 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.770 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.771 # of the computation is cached by cruncher
2025-07-02 06:41:17.771 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.771 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.771 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.771 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.771 if best_ratio < cutoff:
2025-07-02 06:41:17.771 # no non-identical "pretty close" pair
2025-07-02 06:41:17.771 if eqi is None:
2025-07-02 06:41:17.771 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.771 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.771 return
2025-07-02 06:41:17.771 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.771 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.771 else:
2025-07-02 06:41:17.771 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.771 eqi = None
2025-07-02 06:41:17.771
2025-07-02 06:41:17.771 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.771 # identical
2025-07-02 06:41:17.772
2025-07-02 06:41:17.772 # pump out diffs from before the synch point
2025-07-02 06:41:17.772 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.772
2025-07-02 06:41:17.772 # do intraline marking on the synch pair
2025-07-02 06:41:17.772 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.772 if eqi is None:
2025-07-02 06:41:17.772 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.772 atags = btags = ""
2025-07-02 06:41:17.772 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.772 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.772 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.772 if tag == 'replace':
2025-07-02 06:41:17.772 atags += '^' * la
2025-07-02 06:41:17.772 btags += '^' * lb
2025-07-02 06:41:17.772 elif tag == 'delete':
2025-07-02 06:41:17.772 atags += '-' * la
2025-07-02 06:41:17.772 elif tag == 'insert':
2025-07-02 06:41:17.772 btags += '+' * lb
2025-07-02 06:41:17.772 elif tag == 'equal':
2025-07-02 06:41:17.773 atags += ' ' * la
2025-07-02 06:41:17.773 btags += ' ' * lb
2025-07-02 06:41:17.773 else:
2025-07-02 06:41:17.773 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.773 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.773 else:
2025-07-02 06:41:17.773 # the synch pair is identical
2025-07-02 06:41:17.773 yield ' ' + aelt
2025-07-02 06:41:17.773
2025-07-02 06:41:17.773 # pump out diffs from after the synch point
2025-07-02 06:41:17.773 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.773
2025-07-02 06:41:17.773 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.773 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.773
2025-07-02 06:41:17.773 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.773 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.773 alo = 286, ahi = 1101
2025-07-02 06:41:17.774 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.774 blo = 286, bhi = 1101
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.774 g = []
2025-07-02 06:41:17.774 if alo < ahi:
2025-07-02 06:41:17.774 if blo < bhi:
2025-07-02 06:41:17.774 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.774 else:
2025-07-02 06:41:17.774 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.774 elif blo < bhi:
2025-07-02 06:41:17.774 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 > yield from g
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.774 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.775 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.775 alo = 286, ahi = 1101
2025-07-02 06:41:17.775 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.775 blo = 286, bhi = 1101
2025-07-02 06:41:17.775
2025-07-02 06:41:17.775 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.775 r"""
2025-07-02 06:41:17.775 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.775 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.775 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.775 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.775
2025-07-02 06:41:17.775 Example:
2025-07-02 06:41:17.775
2025-07-02 06:41:17.775 >>> d = Differ()
2025-07-02 06:41:17.775 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.775 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.775 >>> print(''.join(results), end="")
2025-07-02 06:41:17.775 - abcDefghiJkl
2025-07-02 06:41:17.776 + abcdefGhijkl
2025-07-02 06:41:17.776 """
2025-07-02 06:41:17.776
2025-07-02 06:41:17.776 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.776 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.776 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.776 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.776 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.776
2025-07-02 06:41:17.776 # search for the pair that matches best without being identical
2025-07-02 06:41:17.776 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.776 # on junk -- unless we have to)
2025-07-02 06:41:17.776 for j in range(blo, bhi):
2025-07-02 06:41:17.776 bj = b[j]
2025-07-02 06:41:17.776 cruncher.set_seq2(bj)
2025-07-02 06:41:17.776 for i in range(alo, ahi):
2025-07-02 06:41:17.776 ai = a[i]
2025-07-02 06:41:17.776 if ai == bj:
2025-07-02 06:41:17.777 if eqi is None:
2025-07-02 06:41:17.777 eqi, eqj = i, j
2025-07-02 06:41:17.777 continue
2025-07-02 06:41:17.777 cruncher.set_seq1(ai)
2025-07-02 06:41:17.777 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.777 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.777 # compares by a factor of 3.
2025-07-02 06:41:17.777 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.777 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.777 # of the computation is cached by cruncher
2025-07-02 06:41:17.777 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.777 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.777 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.777 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.777 if best_ratio < cutoff:
2025-07-02 06:41:17.777 # no non-identical "pretty close" pair
2025-07-02 06:41:17.777 if eqi is None:
2025-07-02 06:41:17.777 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.777 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.778 return
2025-07-02 06:41:17.778 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.778 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.778 else:
2025-07-02 06:41:17.778 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.778 eqi = None
2025-07-02 06:41:17.778
2025-07-02 06:41:17.778 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.778 # identical
2025-07-02 06:41:17.778
2025-07-02 06:41:17.778 # pump out diffs from before the synch point
2025-07-02 06:41:17.778 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.778
2025-07-02 06:41:17.778 # do intraline marking on the synch pair
2025-07-02 06:41:17.778 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.778 if eqi is None:
2025-07-02 06:41:17.778 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.778 atags = btags = ""
2025-07-02 06:41:17.778 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.778 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.779 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.779 if tag == 'replace':
2025-07-02 06:41:17.779 atags += '^' * la
2025-07-02 06:41:17.779 btags += '^' * lb
2025-07-02 06:41:17.779 elif tag == 'delete':
2025-07-02 06:41:17.779 atags += '-' * la
2025-07-02 06:41:17.779 elif tag == 'insert':
2025-07-02 06:41:17.779 btags += '+' * lb
2025-07-02 06:41:17.779 elif tag == 'equal':
2025-07-02 06:41:17.779 atags += ' ' * la
2025-07-02 06:41:17.779 btags += ' ' * lb
2025-07-02 06:41:17.779 else:
2025-07-02 06:41:17.779 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.779 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.779 else:
2025-07-02 06:41:17.779 # the synch pair is identical
2025-07-02 06:41:17.779 yield ' ' + aelt
2025-07-02 06:41:17.779
2025-07-02 06:41:17.779 # pump out diffs from after the synch point
2025-07-02 06:41:17.779 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.780
2025-07-02 06:41:17.780 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.780 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.780
2025-07-02 06:41:17.780 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.780 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.780 alo = 287, ahi = 1101
2025-07-02 06:41:17.780 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.780 blo = 287, bhi = 1101
2025-07-02 06:41:17.780
2025-07-02 06:41:17.780 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.780 g = []
2025-07-02 06:41:17.780 if alo < ahi:
2025-07-02 06:41:17.780 if blo < bhi:
2025-07-02 06:41:17.780 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.780 else:
2025-07-02 06:41:17.780 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.780 elif blo < bhi:
2025-07-02 06:41:17.780 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 > yield from g
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.781 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.781 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.781 alo = 287, ahi = 1101
2025-07-02 06:41:17.781 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.781 blo = 287, bhi = 1101
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.781 r"""
2025-07-02 06:41:17.781 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.781 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.781 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.781 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.781
2025-07-02 06:41:17.782 Example:
2025-07-02 06:41:17.782
2025-07-02 06:41:17.782 >>> d = Differ()
2025-07-02 06:41:17.782 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.782 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.782 >>> print(''.join(results), end="")
2025-07-02 06:41:17.782 - abcDefghiJkl
2025-07-02 06:41:17.782 + abcdefGhijkl
2025-07-02 06:41:17.782 """
2025-07-02 06:41:17.782
2025-07-02 06:41:17.782 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.782 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.782 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.782 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.782 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.782
2025-07-02 06:41:17.782 # search for the pair that matches best without being identical
2025-07-02 06:41:17.782 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.783 # on junk -- unless we have to)
2025-07-02 06:41:17.783 for j in range(blo, bhi):
2025-07-02 06:41:17.783 bj = b[j]
2025-07-02 06:41:17.783 cruncher.set_seq2(bj)
2025-07-02 06:41:17.783 for i in range(alo, ahi):
2025-07-02 06:41:17.783 ai = a[i]
2025-07-02 06:41:17.783 if ai == bj:
2025-07-02 06:41:17.783 if eqi is None:
2025-07-02 06:41:17.783 eqi, eqj = i, j
2025-07-02 06:41:17.783 continue
2025-07-02 06:41:17.783 cruncher.set_seq1(ai)
2025-07-02 06:41:17.783 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.783 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.783 # compares by a factor of 3.
2025-07-02 06:41:17.783 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.783 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.783 # of the computation is cached by cruncher
2025-07-02 06:41:17.783 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.783 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.783 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.783 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.784 if best_ratio < cutoff:
2025-07-02 06:41:17.784 # no non-identical "pretty close" pair
2025-07-02 06:41:17.784 if eqi is None:
2025-07-02 06:41:17.784 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.784 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.784 return
2025-07-02 06:41:17.784 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.784 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.784 else:
2025-07-02 06:41:17.784 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.784 eqi = None
2025-07-02 06:41:17.784
2025-07-02 06:41:17.784 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.784 # identical
2025-07-02 06:41:17.784
2025-07-02 06:41:17.784 # pump out diffs from before the synch point
2025-07-02 06:41:17.784 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.784
2025-07-02 06:41:17.784 # do intraline marking on the synch pair
2025-07-02 06:41:17.784 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.785 if eqi is None:
2025-07-02 06:41:17.785 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.785 atags = btags = ""
2025-07-02 06:41:17.785 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.785 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.785 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.785 if tag == 'replace':
2025-07-02 06:41:17.785 atags += '^' * la
2025-07-02 06:41:17.785 btags += '^' * lb
2025-07-02 06:41:17.785 elif tag == 'delete':
2025-07-02 06:41:17.785 atags += '-' * la
2025-07-02 06:41:17.785 elif tag == 'insert':
2025-07-02 06:41:17.785 btags += '+' * lb
2025-07-02 06:41:17.785 elif tag == 'equal':
2025-07-02 06:41:17.785 atags += ' ' * la
2025-07-02 06:41:17.785 btags += ' ' * lb
2025-07-02 06:41:17.785 else:
2025-07-02 06:41:17.785 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.785 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.785 else:
2025-07-02 06:41:17.786 # the synch pair is identical
2025-07-02 06:41:17.786 yield ' ' + aelt
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786 # pump out diffs from after the synch point
2025-07-02 06:41:17.786 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.786 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.786 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.786 alo = 290, ahi = 1101
2025-07-02 06:41:17.786 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.786 blo = 290, bhi = 1101
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.786 g = []
2025-07-02 06:41:17.786 if alo < ahi:
2025-07-02 06:41:17.786 if blo < bhi:
2025-07-02 06:41:17.786 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.787 else:
2025-07-02 06:41:17.787 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.787 elif blo < bhi:
2025-07-02 06:41:17.787 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 > yield from g
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.787 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.787 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.787 alo = 290, ahi = 1101
2025-07-02 06:41:17.787 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.787 blo = 290, bhi = 1101
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.787 r"""
2025-07-02 06:41:17.787 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.787 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.788 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.788 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.788
2025-07-02 06:41:17.788 Example:
2025-07-02 06:41:17.788
2025-07-02 06:41:17.788 >>> d = Differ()
2025-07-02 06:41:17.788 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.788 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.788 >>> print(''.join(results), end="")
2025-07-02 06:41:17.788 - abcDefghiJkl
2025-07-02 06:41:17.788 + abcdefGhijkl
2025-07-02 06:41:17.788 """
2025-07-02 06:41:17.788
2025-07-02 06:41:17.788 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.788 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.788 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.788 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.789 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.789
2025-07-02 06:41:17.789 # search for the pair that matches best without being identical
2025-07-02 06:41:17.789 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.789 # on junk -- unless we have to)
2025-07-02 06:41:17.789 for j in range(blo, bhi):
2025-07-02 06:41:17.789 bj = b[j]
2025-07-02 06:41:17.789 cruncher.set_seq2(bj)
2025-07-02 06:41:17.789 for i in range(alo, ahi):
2025-07-02 06:41:17.789 ai = a[i]
2025-07-02 06:41:17.789 if ai == bj:
2025-07-02 06:41:17.789 if eqi is None:
2025-07-02 06:41:17.789 eqi, eqj = i, j
2025-07-02 06:41:17.789 continue
2025-07-02 06:41:17.789 cruncher.set_seq1(ai)
2025-07-02 06:41:17.789 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.789 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.789 # compares by a factor of 3.
2025-07-02 06:41:17.789 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.790 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.790 # of the computation is cached by cruncher
2025-07-02 06:41:17.790 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.790 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.790 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.790 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.790 if best_ratio < cutoff:
2025-07-02 06:41:17.790 # no non-identical "pretty close" pair
2025-07-02 06:41:17.790 if eqi is None:
2025-07-02 06:41:17.790 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.790 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.790 return
2025-07-02 06:41:17.790 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.790 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.790 else:
2025-07-02 06:41:17.790 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.790 eqi = None
2025-07-02 06:41:17.790
2025-07-02 06:41:17.790 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.790 # identical
2025-07-02 06:41:17.791
2025-07-02 06:41:17.791 # pump out diffs from before the synch point
2025-07-02 06:41:17.791 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.791
2025-07-02 06:41:17.791 # do intraline marking on the synch pair
2025-07-02 06:41:17.791 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.791 if eqi is None:
2025-07-02 06:41:17.791 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.791 atags = btags = ""
2025-07-02 06:41:17.791 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.791 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.791 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.791 if tag == 'replace':
2025-07-02 06:41:17.791 atags += '^' * la
2025-07-02 06:41:17.791 btags += '^' * lb
2025-07-02 06:41:17.791 elif tag == 'delete':
2025-07-02 06:41:17.791 atags += '-' * la
2025-07-02 06:41:17.791 elif tag == 'insert':
2025-07-02 06:41:17.791 btags += '+' * lb
2025-07-02 06:41:17.791 elif tag == 'equal':
2025-07-02 06:41:17.791 atags += ' ' * la
2025-07-02 06:41:17.792 btags += ' ' * lb
2025-07-02 06:41:17.792 else:
2025-07-02 06:41:17.792 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.792 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.792 else:
2025-07-02 06:41:17.792 # the synch pair is identical
2025-07-02 06:41:17.792 yield ' ' + aelt
2025-07-02 06:41:17.792
2025-07-02 06:41:17.792 # pump out diffs from after the synch point
2025-07-02 06:41:17.792 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.792
2025-07-02 06:41:17.792 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.792 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.792
2025-07-02 06:41:17.792 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.792 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.792 alo = 291, ahi = 1101
2025-07-02 06:41:17.792 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.792 blo = 291, bhi = 1101
2025-07-02 06:41:17.792
2025-07-02 06:41:17.793 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.793 g = []
2025-07-02 06:41:17.793 if alo < ahi:
2025-07-02 06:41:17.793 if blo < bhi:
2025-07-02 06:41:17.793 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.793 else:
2025-07-02 06:41:17.793 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.793 elif blo < bhi:
2025-07-02 06:41:17.793 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.793
2025-07-02 06:41:17.793 > yield from g
2025-07-02 06:41:17.793
2025-07-02 06:41:17.793 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.793 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.793
2025-07-02 06:41:17.793 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.793 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.793 alo = 291, ahi = 1101
2025-07-02 06:41:17.793 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.793 blo = 291, bhi = 1101
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.794 r"""
2025-07-02 06:41:17.794 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.794 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.794 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.794 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794 Example:
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794 >>> d = Differ()
2025-07-02 06:41:17.794 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.794 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.794 >>> print(''.join(results), end="")
2025-07-02 06:41:17.794 - abcDefghiJkl
2025-07-02 06:41:17.794 + abcdefGhijkl
2025-07-02 06:41:17.794 """
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.795 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.795 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.795 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.795 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.795
2025-07-02 06:41:17.795 # search for the pair that matches best without being identical
2025-07-02 06:41:17.795 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.795 # on junk -- unless we have to)
2025-07-02 06:41:17.795 for j in range(blo, bhi):
2025-07-02 06:41:17.795 bj = b[j]
2025-07-02 06:41:17.795 cruncher.set_seq2(bj)
2025-07-02 06:41:17.795 for i in range(alo, ahi):
2025-07-02 06:41:17.795 ai = a[i]
2025-07-02 06:41:17.795 if ai == bj:
2025-07-02 06:41:17.795 if eqi is None:
2025-07-02 06:41:17.795 eqi, eqj = i, j
2025-07-02 06:41:17.795 continue
2025-07-02 06:41:17.795 cruncher.set_seq1(ai)
2025-07-02 06:41:17.795 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.795 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.796 # compares by a factor of 3.
2025-07-02 06:41:17.796 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.796 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.796 # of the computation is cached by cruncher
2025-07-02 06:41:17.796 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.796 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.796 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.796 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.796 if best_ratio < cutoff:
2025-07-02 06:41:17.796 # no non-identical "pretty close" pair
2025-07-02 06:41:17.796 if eqi is None:
2025-07-02 06:41:17.796 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.796 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.796 return
2025-07-02 06:41:17.796 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.796 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.796 else:
2025-07-02 06:41:17.796 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.796 eqi = None
2025-07-02 06:41:17.797
2025-07-02 06:41:17.797 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.797 # identical
2025-07-02 06:41:17.797
2025-07-02 06:41:17.797 # pump out diffs from before the synch point
2025-07-02 06:41:17.797 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.797
2025-07-02 06:41:17.797 # do intraline marking on the synch pair
2025-07-02 06:41:17.797 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.797 if eqi is None:
2025-07-02 06:41:17.797 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.797 atags = btags = ""
2025-07-02 06:41:17.797 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.797 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.797 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.797 if tag == 'replace':
2025-07-02 06:41:17.797 atags += '^' * la
2025-07-02 06:41:17.797 btags += '^' * lb
2025-07-02 06:41:17.797 elif tag == 'delete':
2025-07-02 06:41:17.797 atags += '-' * la
2025-07-02 06:41:17.798 elif tag == 'insert':
2025-07-02 06:41:17.798 btags += '+' * lb
2025-07-02 06:41:17.798 elif tag == 'equal':
2025-07-02 06:41:17.798 atags += ' ' * la
2025-07-02 06:41:17.798 btags += ' ' * lb
2025-07-02 06:41:17.798 else:
2025-07-02 06:41:17.798 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.798 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.798 else:
2025-07-02 06:41:17.798 # the synch pair is identical
2025-07-02 06:41:17.798 yield ' ' + aelt
2025-07-02 06:41:17.798
2025-07-02 06:41:17.798 # pump out diffs from after the synch point
2025-07-02 06:41:17.798 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.798
2025-07-02 06:41:17.798 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.798 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.798
2025-07-02 06:41:17.798 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.799 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.799 alo = 292, ahi = 1101
2025-07-02 06:41:17.799 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.799 blo = 292, bhi = 1101
2025-07-02 06:41:17.799
2025-07-02 06:41:17.799 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.799 g = []
2025-07-02 06:41:17.799 if alo < ahi:
2025-07-02 06:41:17.799 if blo < bhi:
2025-07-02 06:41:17.799 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.799 else:
2025-07-02 06:41:17.799 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.799 elif blo < bhi:
2025-07-02 06:41:17.799 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.799
2025-07-02 06:41:17.799 > yield from g
2025-07-02 06:41:17.799
2025-07-02 06:41:17.799 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.800 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.800 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.800 alo = 292, ahi = 1101
2025-07-02 06:41:17.800 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.800 blo = 292, bhi = 1101
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.800 r"""
2025-07-02 06:41:17.800 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.800 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.800 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.800 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800 Example:
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800 >>> d = Differ()
2025-07-02 06:41:17.800 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.801 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.801 >>> print(''.join(results), end="")
2025-07-02 06:41:17.801 - abcDefghiJkl
2025-07-02 06:41:17.801 + abcdefGhijkl
2025-07-02 06:41:17.801 """
2025-07-02 06:41:17.801
2025-07-02 06:41:17.801 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.801 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.801 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.801 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.801 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.801
2025-07-02 06:41:17.801 # search for the pair that matches best without being identical
2025-07-02 06:41:17.801 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.801 # on junk -- unless we have to)
2025-07-02 06:41:17.801 for j in range(blo, bhi):
2025-07-02 06:41:17.802 bj = b[j]
2025-07-02 06:41:17.802 cruncher.set_seq2(bj)
2025-07-02 06:41:17.802 for i in range(alo, ahi):
2025-07-02 06:41:17.802 ai = a[i]
2025-07-02 06:41:17.802 if ai == bj:
2025-07-02 06:41:17.802 if eqi is None:
2025-07-02 06:41:17.802 eqi, eqj = i, j
2025-07-02 06:41:17.802 continue
2025-07-02 06:41:17.802 cruncher.set_seq1(ai)
2025-07-02 06:41:17.802 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.802 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.802 # compares by a factor of 3.
2025-07-02 06:41:17.802 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.802 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.802 # of the computation is cached by cruncher
2025-07-02 06:41:17.802 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.802 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.802 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.803 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.803 if best_ratio < cutoff:
2025-07-02 06:41:17.803 # no non-identical "pretty close" pair
2025-07-02 06:41:17.803 if eqi is None:
2025-07-02 06:41:17.803 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.803 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.803 return
2025-07-02 06:41:17.803 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.803 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.803 else:
2025-07-02 06:41:17.803 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.803 eqi = None
2025-07-02 06:41:17.803
2025-07-02 06:41:17.803 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.803 # identical
2025-07-02 06:41:17.803
2025-07-02 06:41:17.803 # pump out diffs from before the synch point
2025-07-02 06:41:17.803 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.804
2025-07-02 06:41:17.804 # do intraline marking on the synch pair
2025-07-02 06:41:17.804 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.804 if eqi is None:
2025-07-02 06:41:17.804 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.804 atags = btags = ""
2025-07-02 06:41:17.804 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.804 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.804 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.804 if tag == 'replace':
2025-07-02 06:41:17.804 atags += '^' * la
2025-07-02 06:41:17.804 btags += '^' * lb
2025-07-02 06:41:17.804 elif tag == 'delete':
2025-07-02 06:41:17.804 atags += '-' * la
2025-07-02 06:41:17.804 elif tag == 'insert':
2025-07-02 06:41:17.804 btags += '+' * lb
2025-07-02 06:41:17.804 elif tag == 'equal':
2025-07-02 06:41:17.804 atags += ' ' * la
2025-07-02 06:41:17.804 btags += ' ' * lb
2025-07-02 06:41:17.805 else:
2025-07-02 06:41:17.805 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.805 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.805 else:
2025-07-02 06:41:17.805 # the synch pair is identical
2025-07-02 06:41:17.805 yield ' ' + aelt
2025-07-02 06:41:17.805
2025-07-02 06:41:17.805 # pump out diffs from after the synch point
2025-07-02 06:41:17.805 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.805
2025-07-02 06:41:17.805 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.805 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.805
2025-07-02 06:41:17.805 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.805 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.805 alo = 293, ahi = 1101
2025-07-02 06:41:17.805 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.805 blo = 293, bhi = 1101
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.806 g = []
2025-07-02 06:41:17.806 if alo < ahi:
2025-07-02 06:41:17.806 if blo < bhi:
2025-07-02 06:41:17.806 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.806 else:
2025-07-02 06:41:17.806 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.806 elif blo < bhi:
2025-07-02 06:41:17.806 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 > yield from g
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.806 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.806 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.806 alo = 293, ahi = 1101
2025-07-02 06:41:17.807 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.807 blo = 293, bhi = 1101
2025-07-02 06:41:17.807
2025-07-02 06:41:17.807 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.807 r"""
2025-07-02 06:41:17.807 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.807 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.807 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.807 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.807
2025-07-02 06:41:17.807 Example:
2025-07-02 06:41:17.807
2025-07-02 06:41:17.807 >>> d = Differ()
2025-07-02 06:41:17.807 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.807 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.807 >>> print(''.join(results), end="")
2025-07-02 06:41:17.807 - abcDefghiJkl
2025-07-02 06:41:17.807 + abcdefGhijkl
2025-07-02 06:41:17.808 """
2025-07-02 06:41:17.808
2025-07-02 06:41:17.808 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.808 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.808 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.808 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.808 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.808
2025-07-02 06:41:17.808 # search for the pair that matches best without being identical
2025-07-02 06:41:17.808 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.808 # on junk -- unless we have to)
2025-07-02 06:41:17.808 for j in range(blo, bhi):
2025-07-02 06:41:17.808 bj = b[j]
2025-07-02 06:41:17.808 cruncher.set_seq2(bj)
2025-07-02 06:41:17.808 for i in range(alo, ahi):
2025-07-02 06:41:17.808 ai = a[i]
2025-07-02 06:41:17.808 if ai == bj:
2025-07-02 06:41:17.808 if eqi is None:
2025-07-02 06:41:17.808 eqi, eqj = i, j
2025-07-02 06:41:17.809 continue
2025-07-02 06:41:17.809 cruncher.set_seq1(ai)
2025-07-02 06:41:17.809 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.809 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.809 # compares by a factor of 3.
2025-07-02 06:41:17.809 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.809 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.809 # of the computation is cached by cruncher
2025-07-02 06:41:17.809 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.809 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.809 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.809 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.809 if best_ratio < cutoff:
2025-07-02 06:41:17.809 # no non-identical "pretty close" pair
2025-07-02 06:41:17.809 if eqi is None:
2025-07-02 06:41:17.809 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.809 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.809 return
2025-07-02 06:41:17.809 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.810 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.810 else:
2025-07-02 06:41:17.810 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.810 eqi = None
2025-07-02 06:41:17.810
2025-07-02 06:41:17.810 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.810 # identical
2025-07-02 06:41:17.810
2025-07-02 06:41:17.810 # pump out diffs from before the synch point
2025-07-02 06:41:17.810 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.810
2025-07-02 06:41:17.810 # do intraline marking on the synch pair
2025-07-02 06:41:17.810 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.810 if eqi is None:
2025-07-02 06:41:17.810 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.810 atags = btags = ""
2025-07-02 06:41:17.810 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.810 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.810 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.810 if tag == 'replace':
2025-07-02 06:41:17.811 atags += '^' * la
2025-07-02 06:41:17.811 btags += '^' * lb
2025-07-02 06:41:17.811 elif tag == 'delete':
2025-07-02 06:41:17.811 atags += '-' * la
2025-07-02 06:41:17.811 elif tag == 'insert':
2025-07-02 06:41:17.811 btags += '+' * lb
2025-07-02 06:41:17.811 elif tag == 'equal':
2025-07-02 06:41:17.811 atags += ' ' * la
2025-07-02 06:41:17.811 btags += ' ' * lb
2025-07-02 06:41:17.811 else:
2025-07-02 06:41:17.811 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.811 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.811 else:
2025-07-02 06:41:17.811 # the synch pair is identical
2025-07-02 06:41:17.811 yield ' ' + aelt
2025-07-02 06:41:17.811
2025-07-02 06:41:17.811 # pump out diffs from after the synch point
2025-07-02 06:41:17.811 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.811
2025-07-02 06:41:17.811 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.812 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.812
2025-07-02 06:41:17.812 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.812 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.812 alo = 294, ahi = 1101
2025-07-02 06:41:17.812 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.812 blo = 294, bhi = 1101
2025-07-02 06:41:17.812
2025-07-02 06:41:17.812 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.812 g = []
2025-07-02 06:41:17.812 if alo < ahi:
2025-07-02 06:41:17.812 if blo < bhi:
2025-07-02 06:41:17.812 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.812 else:
2025-07-02 06:41:17.812 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.812 elif blo < bhi:
2025-07-02 06:41:17.812 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.812
2025-07-02 06:41:17.812 > yield from g
2025-07-02 06:41:17.812
2025-07-02 06:41:17.813 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.813 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.813 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.813 alo = 294, ahi = 1101
2025-07-02 06:41:17.813 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.813 blo = 294, bhi = 1101
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.813 r"""
2025-07-02 06:41:17.813 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.813 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.813 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.813 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813 Example:
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813 >>> d = Differ()
2025-07-02 06:41:17.813 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.814 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.814 >>> print(''.join(results), end="")
2025-07-02 06:41:17.814 - abcDefghiJkl
2025-07-02 06:41:17.814 + abcdefGhijkl
2025-07-02 06:41:17.814 """
2025-07-02 06:41:17.814
2025-07-02 06:41:17.814 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.814 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.814 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.814 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.814 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.814
2025-07-02 06:41:17.814 # search for the pair that matches best without being identical
2025-07-02 06:41:17.814 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.814 # on junk -- unless we have to)
2025-07-02 06:41:17.814 for j in range(blo, bhi):
2025-07-02 06:41:17.814 bj = b[j]
2025-07-02 06:41:17.814 cruncher.set_seq2(bj)
2025-07-02 06:41:17.814 for i in range(alo, ahi):
2025-07-02 06:41:17.815 ai = a[i]
2025-07-02 06:41:17.815 if ai == bj:
2025-07-02 06:41:17.815 if eqi is None:
2025-07-02 06:41:17.815 eqi, eqj = i, j
2025-07-02 06:41:17.815 continue
2025-07-02 06:41:17.815 cruncher.set_seq1(ai)
2025-07-02 06:41:17.815 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.815 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.815 # compares by a factor of 3.
2025-07-02 06:41:17.815 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.815 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.815 # of the computation is cached by cruncher
2025-07-02 06:41:17.815 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.815 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.815 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.815 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.815 if best_ratio < cutoff:
2025-07-02 06:41:17.815 # no non-identical "pretty close" pair
2025-07-02 06:41:17.816 if eqi is None:
2025-07-02 06:41:17.816 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.816 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.816 return
2025-07-02 06:41:17.816 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.816 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.816 else:
2025-07-02 06:41:17.816 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.816 eqi = None
2025-07-02 06:41:17.816
2025-07-02 06:41:17.816 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.816 # identical
2025-07-02 06:41:17.816
2025-07-02 06:41:17.816 # pump out diffs from before the synch point
2025-07-02 06:41:17.816 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.816
2025-07-02 06:41:17.816 # do intraline marking on the synch pair
2025-07-02 06:41:17.816 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.816 if eqi is None:
2025-07-02 06:41:17.816 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.817 atags = btags = ""
2025-07-02 06:41:17.817 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.817 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.817 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.817 if tag == 'replace':
2025-07-02 06:41:17.817 atags += '^' * la
2025-07-02 06:41:17.817 btags += '^' * lb
2025-07-02 06:41:17.817 elif tag == 'delete':
2025-07-02 06:41:17.817 atags += '-' * la
2025-07-02 06:41:17.817 elif tag == 'insert':
2025-07-02 06:41:17.817 btags += '+' * lb
2025-07-02 06:41:17.817 elif tag == 'equal':
2025-07-02 06:41:17.817 atags += ' ' * la
2025-07-02 06:41:17.817 btags += ' ' * lb
2025-07-02 06:41:17.817 else:
2025-07-02 06:41:17.817 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.817 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.817 else:
2025-07-02 06:41:17.817 # the synch pair is identical
2025-07-02 06:41:17.817 yield ' ' + aelt
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818 # pump out diffs from after the synch point
2025-07-02 06:41:17.818 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.818 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.818 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.818 alo = 295, ahi = 1101
2025-07-02 06:41:17.818 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.818 blo = 295, bhi = 1101
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.818 g = []
2025-07-02 06:41:17.818 if alo < ahi:
2025-07-02 06:41:17.818 if blo < bhi:
2025-07-02 06:41:17.818 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.818 else:
2025-07-02 06:41:17.818 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.819 elif blo < bhi:
2025-07-02 06:41:17.819 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 > yield from g
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.819 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.819 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.819 alo = 295, ahi = 1101
2025-07-02 06:41:17.819 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.819 blo = 295, bhi = 1101
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.819 r"""
2025-07-02 06:41:17.819 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.819 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.819 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.819 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.819
2025-07-02 06:41:17.820 Example:
2025-07-02 06:41:17.820
2025-07-02 06:41:17.820 >>> d = Differ()
2025-07-02 06:41:17.820 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.820 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.820 >>> print(''.join(results), end="")
2025-07-02 06:41:17.820 - abcDefghiJkl
2025-07-02 06:41:17.820 + abcdefGhijkl
2025-07-02 06:41:17.820 """
2025-07-02 06:41:17.820
2025-07-02 06:41:17.820 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.820 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.820 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.820 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.820 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.820
2025-07-02 06:41:17.820 # search for the pair that matches best without being identical
2025-07-02 06:41:17.820 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.821 # on junk -- unless we have to)
2025-07-02 06:41:17.821 for j in range(blo, bhi):
2025-07-02 06:41:17.821 bj = b[j]
2025-07-02 06:41:17.821 cruncher.set_seq2(bj)
2025-07-02 06:41:17.821 for i in range(alo, ahi):
2025-07-02 06:41:17.821 ai = a[i]
2025-07-02 06:41:17.821 if ai == bj:
2025-07-02 06:41:17.821 if eqi is None:
2025-07-02 06:41:17.821 eqi, eqj = i, j
2025-07-02 06:41:17.821 continue
2025-07-02 06:41:17.821 cruncher.set_seq1(ai)
2025-07-02 06:41:17.821 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.821 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.821 # compares by a factor of 3.
2025-07-02 06:41:17.821 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.821 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.821 # of the computation is cached by cruncher
2025-07-02 06:41:17.821 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.822 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.822 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.822 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.822 if best_ratio < cutoff:
2025-07-02 06:41:17.822 # no non-identical "pretty close" pair
2025-07-02 06:41:17.822 if eqi is None:
2025-07-02 06:41:17.822 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.822 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.822 return
2025-07-02 06:41:17.822 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.822 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.822 else:
2025-07-02 06:41:17.822 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.822 eqi = None
2025-07-02 06:41:17.822
2025-07-02 06:41:17.822 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.822 # identical
2025-07-02 06:41:17.822
2025-07-02 06:41:17.822 # pump out diffs from before the synch point
2025-07-02 06:41:17.822 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.823
2025-07-02 06:41:17.823 # do intraline marking on the synch pair
2025-07-02 06:41:17.823 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.823 if eqi is None:
2025-07-02 06:41:17.823 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.823 atags = btags = ""
2025-07-02 06:41:17.823 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.823 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.823 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.823 if tag == 'replace':
2025-07-02 06:41:17.823 atags += '^' * la
2025-07-02 06:41:17.823 btags += '^' * lb
2025-07-02 06:41:17.823 elif tag == 'delete':
2025-07-02 06:41:17.823 atags += '-' * la
2025-07-02 06:41:17.823 elif tag == 'insert':
2025-07-02 06:41:17.823 btags += '+' * lb
2025-07-02 06:41:17.823 elif tag == 'equal':
2025-07-02 06:41:17.823 atags += ' ' * la
2025-07-02 06:41:17.823 btags += ' ' * lb
2025-07-02 06:41:17.824 else:
2025-07-02 06:41:17.824 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.824 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.824 else:
2025-07-02 06:41:17.824 # the synch pair is identical
2025-07-02 06:41:17.824 yield ' ' + aelt
2025-07-02 06:41:17.824
2025-07-02 06:41:17.824 # pump out diffs from after the synch point
2025-07-02 06:41:17.824 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.824
2025-07-02 06:41:17.824 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.824 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.824
2025-07-02 06:41:17.824 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.824 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.824 alo = 296, ahi = 1101
2025-07-02 06:41:17.824 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.824 blo = 296, bhi = 1101
2025-07-02 06:41:17.824
2025-07-02 06:41:17.825 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.825 g = []
2025-07-02 06:41:17.825 if alo < ahi:
2025-07-02 06:41:17.825 if blo < bhi:
2025-07-02 06:41:17.825 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.825 else:
2025-07-02 06:41:17.825 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.825 elif blo < bhi:
2025-07-02 06:41:17.825 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.825
2025-07-02 06:41:17.825 > yield from g
2025-07-02 06:41:17.825
2025-07-02 06:41:17.825 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.825 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.825
2025-07-02 06:41:17.825 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.825 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.825 alo = 296, ahi = 1101
2025-07-02 06:41:17.825 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.825 blo = 296, bhi = 1101
2025-07-02 06:41:17.826
2025-07-02 06:41:17.826 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.826 r"""
2025-07-02 06:41:17.826 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.826 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.826 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.826 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.826
2025-07-02 06:41:17.826 Example:
2025-07-02 06:41:17.826
2025-07-02 06:41:17.826 >>> d = Differ()
2025-07-02 06:41:17.826 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.826 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.826 >>> print(''.join(results), end="")
2025-07-02 06:41:17.826 - abcDefghiJkl
2025-07-02 06:41:17.826 + abcdefGhijkl
2025-07-02 06:41:17.826 """
2025-07-02 06:41:17.826
2025-07-02 06:41:17.827 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.827 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.827 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.827 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.827 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.827
2025-07-02 06:41:17.827 # search for the pair that matches best without being identical
2025-07-02 06:41:17.827 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.827 # on junk -- unless we have to)
2025-07-02 06:41:17.827 for j in range(blo, bhi):
2025-07-02 06:41:17.827 bj = b[j]
2025-07-02 06:41:17.827 cruncher.set_seq2(bj)
2025-07-02 06:41:17.827 for i in range(alo, ahi):
2025-07-02 06:41:17.827 ai = a[i]
2025-07-02 06:41:17.827 if ai == bj:
2025-07-02 06:41:17.827 if eqi is None:
2025-07-02 06:41:17.827 eqi, eqj = i, j
2025-07-02 06:41:17.827 continue
2025-07-02 06:41:17.827 cruncher.set_seq1(ai)
2025-07-02 06:41:17.827 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.827 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.828 # compares by a factor of 3.
2025-07-02 06:41:17.828 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.828 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.828 # of the computation is cached by cruncher
2025-07-02 06:41:17.828 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.828 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.828 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.828 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.828 if best_ratio < cutoff:
2025-07-02 06:41:17.828 # no non-identical "pretty close" pair
2025-07-02 06:41:17.828 if eqi is None:
2025-07-02 06:41:17.828 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.828 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.828 return
2025-07-02 06:41:17.828 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.828 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.828 else:
2025-07-02 06:41:17.828 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.828 eqi = None
2025-07-02 06:41:17.829
2025-07-02 06:41:17.829 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.829 # identical
2025-07-02 06:41:17.829
2025-07-02 06:41:17.829 # pump out diffs from before the synch point
2025-07-02 06:41:17.829 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.829
2025-07-02 06:41:17.829 # do intraline marking on the synch pair
2025-07-02 06:41:17.829 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.829 if eqi is None:
2025-07-02 06:41:17.829 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.829 atags = btags = ""
2025-07-02 06:41:17.829 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.829 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.829 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.829 if tag == 'replace':
2025-07-02 06:41:17.829 atags += '^' * la
2025-07-02 06:41:17.829 btags += '^' * lb
2025-07-02 06:41:17.829 elif tag == 'delete':
2025-07-02 06:41:17.829 atags += '-' * la
2025-07-02 06:41:17.829 elif tag == 'insert':
2025-07-02 06:41:17.830 btags += '+' * lb
2025-07-02 06:41:17.830 elif tag == 'equal':
2025-07-02 06:41:17.830 atags += ' ' * la
2025-07-02 06:41:17.830 btags += ' ' * lb
2025-07-02 06:41:17.830 else:
2025-07-02 06:41:17.830 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.830 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.830 else:
2025-07-02 06:41:17.830 # the synch pair is identical
2025-07-02 06:41:17.830 yield ' ' + aelt
2025-07-02 06:41:17.830
2025-07-02 06:41:17.830 # pump out diffs from after the synch point
2025-07-02 06:41:17.830 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.830
2025-07-02 06:41:17.830 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.830 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.830
2025-07-02 06:41:17.830 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.830 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.830 alo = 297, ahi = 1101
2025-07-02 06:41:17.831 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.831 blo = 297, bhi = 1101
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.831 g = []
2025-07-02 06:41:17.831 if alo < ahi:
2025-07-02 06:41:17.831 if blo < bhi:
2025-07-02 06:41:17.831 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.831 else:
2025-07-02 06:41:17.831 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.831 elif blo < bhi:
2025-07-02 06:41:17.831 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 > yield from g
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.831 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.831 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.832 alo = 297, ahi = 1101
2025-07-02 06:41:17.832 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.832 blo = 297, bhi = 1101
2025-07-02 06:41:17.832
2025-07-02 06:41:17.832 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.832 r"""
2025-07-02 06:41:17.832 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.832 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.832 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.832 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.832
2025-07-02 06:41:17.832 Example:
2025-07-02 06:41:17.832
2025-07-02 06:41:17.832 >>> d = Differ()
2025-07-02 06:41:17.832 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.832 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.832 >>> print(''.join(results), end="")
2025-07-02 06:41:17.832 - abcDefghiJkl
2025-07-02 06:41:17.833 + abcdefGhijkl
2025-07-02 06:41:17.833 """
2025-07-02 06:41:17.833
2025-07-02 06:41:17.833 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.833 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.833 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.833 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.833 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.833
2025-07-02 06:41:17.833 # search for the pair that matches best without being identical
2025-07-02 06:41:17.833 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.833 # on junk -- unless we have to)
2025-07-02 06:41:17.833 for j in range(blo, bhi):
2025-07-02 06:41:17.833 bj = b[j]
2025-07-02 06:41:17.833 cruncher.set_seq2(bj)
2025-07-02 06:41:17.833 for i in range(alo, ahi):
2025-07-02 06:41:17.833 ai = a[i]
2025-07-02 06:41:17.833 if ai == bj:
2025-07-02 06:41:17.833 if eqi is None:
2025-07-02 06:41:17.834 eqi, eqj = i, j
2025-07-02 06:41:17.834 continue
2025-07-02 06:41:17.834 cruncher.set_seq1(ai)
2025-07-02 06:41:17.834 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.834 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.834 # compares by a factor of 3.
2025-07-02 06:41:17.834 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.834 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.834 # of the computation is cached by cruncher
2025-07-02 06:41:17.834 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.834 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.834 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.834 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.834 if best_ratio < cutoff:
2025-07-02 06:41:17.834 # no non-identical "pretty close" pair
2025-07-02 06:41:17.834 if eqi is None:
2025-07-02 06:41:17.834 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.834 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.834 return
2025-07-02 06:41:17.834 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.835 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.835 else:
2025-07-02 06:41:17.835 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.835 eqi = None
2025-07-02 06:41:17.835
2025-07-02 06:41:17.835 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.835 # identical
2025-07-02 06:41:17.835
2025-07-02 06:41:17.835 # pump out diffs from before the synch point
2025-07-02 06:41:17.835 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.835
2025-07-02 06:41:17.835 # do intraline marking on the synch pair
2025-07-02 06:41:17.835 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.835 if eqi is None:
2025-07-02 06:41:17.835 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.835 atags = btags = ""
2025-07-02 06:41:17.835 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.835 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.836 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.836 if tag == 'replace':
2025-07-02 06:41:17.836 atags += '^' * la
2025-07-02 06:41:17.836 btags += '^' * lb
2025-07-02 06:41:17.836 elif tag == 'delete':
2025-07-02 06:41:17.836 atags += '-' * la
2025-07-02 06:41:17.836 elif tag == 'insert':
2025-07-02 06:41:17.836 btags += '+' * lb
2025-07-02 06:41:17.836 elif tag == 'equal':
2025-07-02 06:41:17.836 atags += ' ' * la
2025-07-02 06:41:17.836 btags += ' ' * lb
2025-07-02 06:41:17.836 else:
2025-07-02 06:41:17.836 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.836 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.836 else:
2025-07-02 06:41:17.836 # the synch pair is identical
2025-07-02 06:41:17.836 yield ' ' + aelt
2025-07-02 06:41:17.836
2025-07-02 06:41:17.836 # pump out diffs from after the synch point
2025-07-02 06:41:17.836 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.837
2025-07-02 06:41:17.837 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.837 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.837
2025-07-02 06:41:17.837 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.837 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.837 alo = 298, ahi = 1101
2025-07-02 06:41:17.837 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.837 blo = 298, bhi = 1101
2025-07-02 06:41:17.837
2025-07-02 06:41:17.837 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.837 g = []
2025-07-02 06:41:17.837 if alo < ahi:
2025-07-02 06:41:17.837 if blo < bhi:
2025-07-02 06:41:17.837 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.837 else:
2025-07-02 06:41:17.837 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.838 elif blo < bhi:
2025-07-02 06:41:17.838 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 > yield from g
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.838 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.838 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.838 alo = 298, ahi = 1101
2025-07-02 06:41:17.838 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.838 blo = 298, bhi = 1101
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.838 r"""
2025-07-02 06:41:17.838 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.838 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.838 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.838 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839 Example:
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839 >>> d = Differ()
2025-07-02 06:41:17.839 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.839 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.839 >>> print(''.join(results), end="")
2025-07-02 06:41:17.839 - abcDefghiJkl
2025-07-02 06:41:17.839 + abcdefGhijkl
2025-07-02 06:41:17.839 """
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.839 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.839 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.839 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.839 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839 # search for the pair that matches best without being identical
2025-07-02 06:41:17.839 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.840 # on junk -- unless we have to)
2025-07-02 06:41:17.840 for j in range(blo, bhi):
2025-07-02 06:41:17.840 bj = b[j]
2025-07-02 06:41:17.840 cruncher.set_seq2(bj)
2025-07-02 06:41:17.840 for i in range(alo, ahi):
2025-07-02 06:41:17.840 ai = a[i]
2025-07-02 06:41:17.840 if ai == bj:
2025-07-02 06:41:17.840 if eqi is None:
2025-07-02 06:41:17.840 eqi, eqj = i, j
2025-07-02 06:41:17.840 continue
2025-07-02 06:41:17.840 cruncher.set_seq1(ai)
2025-07-02 06:41:17.840 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.840 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.840 # compares by a factor of 3.
2025-07-02 06:41:17.840 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.840 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.840 # of the computation is cached by cruncher
2025-07-02 06:41:17.840 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.840 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.840 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.841 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.841 if best_ratio < cutoff:
2025-07-02 06:41:17.841 # no non-identical "pretty close" pair
2025-07-02 06:41:17.841 if eqi is None:
2025-07-02 06:41:17.841 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.841 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.841 return
2025-07-02 06:41:17.841 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.841 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.841 else:
2025-07-02 06:41:17.841 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.841 eqi = None
2025-07-02 06:41:17.841
2025-07-02 06:41:17.841 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.841 # identical
2025-07-02 06:41:17.841
2025-07-02 06:41:17.841 # pump out diffs from before the synch point
2025-07-02 06:41:17.841 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.841
2025-07-02 06:41:17.842 # do intraline marking on the synch pair
2025-07-02 06:41:17.842 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.842 if eqi is None:
2025-07-02 06:41:17.842 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.842 atags = btags = ""
2025-07-02 06:41:17.842 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.842 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.842 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.842 if tag == 'replace':
2025-07-02 06:41:17.842 atags += '^' * la
2025-07-02 06:41:17.842 btags += '^' * lb
2025-07-02 06:41:17.842 elif tag == 'delete':
2025-07-02 06:41:17.842 atags += '-' * la
2025-07-02 06:41:17.842 elif tag == 'insert':
2025-07-02 06:41:17.842 btags += '+' * lb
2025-07-02 06:41:17.842 elif tag == 'equal':
2025-07-02 06:41:17.842 atags += ' ' * la
2025-07-02 06:41:17.842 btags += ' ' * lb
2025-07-02 06:41:17.842 else:
2025-07-02 06:41:17.842 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.843 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.843 else:
2025-07-02 06:41:17.843 # the synch pair is identical
2025-07-02 06:41:17.843 yield ' ' + aelt
2025-07-02 06:41:17.843
2025-07-02 06:41:17.843 # pump out diffs from after the synch point
2025-07-02 06:41:17.843 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.843
2025-07-02 06:41:17.843 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.843 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.843
2025-07-02 06:41:17.843 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.843 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.843 alo = 299, ahi = 1101
2025-07-02 06:41:17.843 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.843 blo = 299, bhi = 1101
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.844 g = []
2025-07-02 06:41:17.844 if alo < ahi:
2025-07-02 06:41:17.844 if blo < bhi:
2025-07-02 06:41:17.844 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.844 else:
2025-07-02 06:41:17.844 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.844 elif blo < bhi:
2025-07-02 06:41:17.844 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 > yield from g
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.844 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.844 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.844 alo = 299, ahi = 1101
2025-07-02 06:41:17.844 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.845 blo = 299, bhi = 1101
2025-07-02 06:41:17.845
2025-07-02 06:41:17.845 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.845 r"""
2025-07-02 06:41:17.845 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.845 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.845 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.845 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.845
2025-07-02 06:41:17.845 Example:
2025-07-02 06:41:17.845
2025-07-02 06:41:17.845 >>> d = Differ()
2025-07-02 06:41:17.845 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.845 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.845 >>> print(''.join(results), end="")
2025-07-02 06:41:17.845 - abcDefghiJkl
2025-07-02 06:41:17.845 + abcdefGhijkl
2025-07-02 06:41:17.845 """
2025-07-02 06:41:17.845
2025-07-02 06:41:17.846 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.846 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.846 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.846 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.846 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.846
2025-07-02 06:41:17.846 # search for the pair that matches best without being identical
2025-07-02 06:41:17.846 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.846 # on junk -- unless we have to)
2025-07-02 06:41:17.846 for j in range(blo, bhi):
2025-07-02 06:41:17.846 bj = b[j]
2025-07-02 06:41:17.846 cruncher.set_seq2(bj)
2025-07-02 06:41:17.846 for i in range(alo, ahi):
2025-07-02 06:41:17.846 ai = a[i]
2025-07-02 06:41:17.846 if ai == bj:
2025-07-02 06:41:17.846 if eqi is None:
2025-07-02 06:41:17.846 eqi, eqj = i, j
2025-07-02 06:41:17.846 continue
2025-07-02 06:41:17.846 cruncher.set_seq1(ai)
2025-07-02 06:41:17.846 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.847 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.847 # compares by a factor of 3.
2025-07-02 06:41:17.847 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.847 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.847 # of the computation is cached by cruncher
2025-07-02 06:41:17.847 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.847 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.847 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.847 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.847 if best_ratio < cutoff:
2025-07-02 06:41:17.847 # no non-identical "pretty close" pair
2025-07-02 06:41:17.847 if eqi is None:
2025-07-02 06:41:17.847 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.847 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.847 return
2025-07-02 06:41:17.847 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.847 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.847 else:
2025-07-02 06:41:17.847 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.847 eqi = None
2025-07-02 06:41:17.848
2025-07-02 06:41:17.848 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.848 # identical
2025-07-02 06:41:17.848
2025-07-02 06:41:17.848 # pump out diffs from before the synch point
2025-07-02 06:41:17.848 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.848
2025-07-02 06:41:17.848 # do intraline marking on the synch pair
2025-07-02 06:41:17.848 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.848 if eqi is None:
2025-07-02 06:41:17.848 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.848 atags = btags = ""
2025-07-02 06:41:17.848 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.848 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.848 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.848 if tag == 'replace':
2025-07-02 06:41:17.848 atags += '^' * la
2025-07-02 06:41:17.848 btags += '^' * lb
2025-07-02 06:41:17.848 elif tag == 'delete':
2025-07-02 06:41:17.848 atags += '-' * la
2025-07-02 06:41:17.848 elif tag == 'insert':
2025-07-02 06:41:17.849 btags += '+' * lb
2025-07-02 06:41:17.849 elif tag == 'equal':
2025-07-02 06:41:17.849 atags += ' ' * la
2025-07-02 06:41:17.849 btags += ' ' * lb
2025-07-02 06:41:17.849 else:
2025-07-02 06:41:17.849 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.849 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.849 else:
2025-07-02 06:41:17.849 # the synch pair is identical
2025-07-02 06:41:17.849 yield ' ' + aelt
2025-07-02 06:41:17.849
2025-07-02 06:41:17.849 # pump out diffs from after the synch point
2025-07-02 06:41:17.849 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.849
2025-07-02 06:41:17.849 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.849 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.849
2025-07-02 06:41:17.849 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.849 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.849 alo = 300, ahi = 1101
2025-07-02 06:41:17.850 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.850 blo = 300, bhi = 1101
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.850 g = []
2025-07-02 06:41:17.850 if alo < ahi:
2025-07-02 06:41:17.850 if blo < bhi:
2025-07-02 06:41:17.850 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.850 else:
2025-07-02 06:41:17.850 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.850 elif blo < bhi:
2025-07-02 06:41:17.850 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 > yield from g
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.850 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.851 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.851 alo = 300, ahi = 1101
2025-07-02 06:41:17.851 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.851 blo = 300, bhi = 1101
2025-07-02 06:41:17.851
2025-07-02 06:41:17.851 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.851 r"""
2025-07-02 06:41:17.851 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.851 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.851 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.851 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.851
2025-07-02 06:41:17.851 Example:
2025-07-02 06:41:17.851
2025-07-02 06:41:17.851 >>> d = Differ()
2025-07-02 06:41:17.851 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.851 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.851 >>> print(''.join(results), end="")
2025-07-02 06:41:17.851 - abcDefghiJkl
2025-07-02 06:41:17.852 + abcdefGhijkl
2025-07-02 06:41:17.852 """
2025-07-02 06:41:17.852
2025-07-02 06:41:17.852 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.852 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.852 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.852 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.852 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.852
2025-07-02 06:41:17.852 # search for the pair that matches best without being identical
2025-07-02 06:41:17.852 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.852 # on junk -- unless we have to)
2025-07-02 06:41:17.852 for j in range(blo, bhi):
2025-07-02 06:41:17.852 bj = b[j]
2025-07-02 06:41:17.852 cruncher.set_seq2(bj)
2025-07-02 06:41:17.852 for i in range(alo, ahi):
2025-07-02 06:41:17.852 ai = a[i]
2025-07-02 06:41:17.852 if ai == bj:
2025-07-02 06:41:17.852 if eqi is None:
2025-07-02 06:41:17.853 eqi, eqj = i, j
2025-07-02 06:41:17.853 continue
2025-07-02 06:41:17.853 cruncher.set_seq1(ai)
2025-07-02 06:41:17.853 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.853 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.853 # compares by a factor of 3.
2025-07-02 06:41:17.853 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.853 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.853 # of the computation is cached by cruncher
2025-07-02 06:41:17.853 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.853 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.853 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.853 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.853 if best_ratio < cutoff:
2025-07-02 06:41:17.853 # no non-identical "pretty close" pair
2025-07-02 06:41:17.853 if eqi is None:
2025-07-02 06:41:17.853 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.854 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.854 return
2025-07-02 06:41:17.854 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.854 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.854 else:
2025-07-02 06:41:17.854 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.854 eqi = None
2025-07-02 06:41:17.854
2025-07-02 06:41:17.854 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.854 # identical
2025-07-02 06:41:17.854
2025-07-02 06:41:17.854 # pump out diffs from before the synch point
2025-07-02 06:41:17.854 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.854
2025-07-02 06:41:17.854 # do intraline marking on the synch pair
2025-07-02 06:41:17.854 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.854 if eqi is None:
2025-07-02 06:41:17.854 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.854 atags = btags = ""
2025-07-02 06:41:17.855 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.855 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.855 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.855 if tag == 'replace':
2025-07-02 06:41:17.855 atags += '^' * la
2025-07-02 06:41:17.855 btags += '^' * lb
2025-07-02 06:41:17.855 elif tag == 'delete':
2025-07-02 06:41:17.855 atags += '-' * la
2025-07-02 06:41:17.855 elif tag == 'insert':
2025-07-02 06:41:17.855 btags += '+' * lb
2025-07-02 06:41:17.855 elif tag == 'equal':
2025-07-02 06:41:17.855 atags += ' ' * la
2025-07-02 06:41:17.855 btags += ' ' * lb
2025-07-02 06:41:17.855 else:
2025-07-02 06:41:17.855 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.855 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.855 else:
2025-07-02 06:41:17.855 # the synch pair is identical
2025-07-02 06:41:17.855 yield ' ' + aelt
2025-07-02 06:41:17.855
2025-07-02 06:41:17.856 # pump out diffs from after the synch point
2025-07-02 06:41:17.856 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.856
2025-07-02 06:41:17.856 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.856 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.856
2025-07-02 06:41:17.856 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.856 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.856 alo = 301, ahi = 1101
2025-07-02 06:41:17.856 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.856 blo = 301, bhi = 1101
2025-07-02 06:41:17.856
2025-07-02 06:41:17.856 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.856 g = []
2025-07-02 06:41:17.856 if alo < ahi:
2025-07-02 06:41:17.856 if blo < bhi:
2025-07-02 06:41:17.856 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.856 else:
2025-07-02 06:41:17.856 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.857 elif blo < bhi:
2025-07-02 06:41:17.857 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 > yield from g
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.857 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.857 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.857 alo = 301, ahi = 1101
2025-07-02 06:41:17.857 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.857 blo = 301, bhi = 1101
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.857 r"""
2025-07-02 06:41:17.857 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.857 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.857 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.857 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.858
2025-07-02 06:41:17.858 Example:
2025-07-02 06:41:17.858
2025-07-02 06:41:17.858 >>> d = Differ()
2025-07-02 06:41:17.858 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.858 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.858 >>> print(''.join(results), end="")
2025-07-02 06:41:17.858 - abcDefghiJkl
2025-07-02 06:41:17.858 + abcdefGhijkl
2025-07-02 06:41:17.858 """
2025-07-02 06:41:17.858
2025-07-02 06:41:17.858 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.858 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.858 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.858 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.858 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.859
2025-07-02 06:41:17.859 # search for the pair that matches best without being identical
2025-07-02 06:41:17.859 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.859 # on junk -- unless we have to)
2025-07-02 06:41:17.859 for j in range(blo, bhi):
2025-07-02 06:41:17.859 bj = b[j]
2025-07-02 06:41:17.859 cruncher.set_seq2(bj)
2025-07-02 06:41:17.859 for i in range(alo, ahi):
2025-07-02 06:41:17.859 ai = a[i]
2025-07-02 06:41:17.859 if ai == bj:
2025-07-02 06:41:17.859 if eqi is None:
2025-07-02 06:41:17.859 eqi, eqj = i, j
2025-07-02 06:41:17.859 continue
2025-07-02 06:41:17.859 cruncher.set_seq1(ai)
2025-07-02 06:41:17.859 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.859 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.859 # compares by a factor of 3.
2025-07-02 06:41:17.859 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.859 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.860 # of the computation is cached by cruncher
2025-07-02 06:41:17.860 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.860 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.860 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.860 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.860 if best_ratio < cutoff:
2025-07-02 06:41:17.860 # no non-identical "pretty close" pair
2025-07-02 06:41:17.860 if eqi is None:
2025-07-02 06:41:17.860 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.860 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.860 return
2025-07-02 06:41:17.860 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.860 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.860 else:
2025-07-02 06:41:17.860 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.860 eqi = None
2025-07-02 06:41:17.860
2025-07-02 06:41:17.860 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.860 # identical
2025-07-02 06:41:17.861
2025-07-02 06:41:17.861 # pump out diffs from before the synch point
2025-07-02 06:41:17.861 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.861
2025-07-02 06:41:17.861 # do intraline marking on the synch pair
2025-07-02 06:41:17.861 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.861 if eqi is None:
2025-07-02 06:41:17.861 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.861 atags = btags = ""
2025-07-02 06:41:17.861 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.861 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.861 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.861 if tag == 'replace':
2025-07-02 06:41:17.861 atags += '^' * la
2025-07-02 06:41:17.861 btags += '^' * lb
2025-07-02 06:41:17.861 elif tag == 'delete':
2025-07-02 06:41:17.861 atags += '-' * la
2025-07-02 06:41:17.861 elif tag == 'insert':
2025-07-02 06:41:17.861 btags += '+' * lb
2025-07-02 06:41:17.861 elif tag == 'equal':
2025-07-02 06:41:17.861 atags += ' ' * la
2025-07-02 06:41:17.862 btags += ' ' * lb
2025-07-02 06:41:17.862 else:
2025-07-02 06:41:17.862 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.862 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.862 else:
2025-07-02 06:41:17.862 # the synch pair is identical
2025-07-02 06:41:17.862 yield ' ' + aelt
2025-07-02 06:41:17.862
2025-07-02 06:41:17.862 # pump out diffs from after the synch point
2025-07-02 06:41:17.862 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.862
2025-07-02 06:41:17.862 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.862 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.862
2025-07-02 06:41:17.862 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.862 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.862 alo = 302, ahi = 1101
2025-07-02 06:41:17.862 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.862 blo = 302, bhi = 1101
2025-07-02 06:41:17.862
2025-07-02 06:41:17.863 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.863 g = []
2025-07-02 06:41:17.863 if alo < ahi:
2025-07-02 06:41:17.863 if blo < bhi:
2025-07-02 06:41:17.863 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.863 else:
2025-07-02 06:41:17.863 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.863 elif blo < bhi:
2025-07-02 06:41:17.863 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.863
2025-07-02 06:41:17.863 > yield from g
2025-07-02 06:41:17.863
2025-07-02 06:41:17.863 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.863 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.863
2025-07-02 06:41:17.863 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.863 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.863 alo = 302, ahi = 1101
2025-07-02 06:41:17.863 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.863 blo = 302, bhi = 1101
2025-07-02 06:41:17.864
2025-07-02 06:41:17.864 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.864 r"""
2025-07-02 06:41:17.864 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.864 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.864 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.864 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.864
2025-07-02 06:41:17.864 Example:
2025-07-02 06:41:17.864
2025-07-02 06:41:17.864 >>> d = Differ()
2025-07-02 06:41:17.864 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.864 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.864 >>> print(''.join(results), end="")
2025-07-02 06:41:17.864 - abcDefghiJkl
2025-07-02 06:41:17.864 + abcdefGhijkl
2025-07-02 06:41:17.864 """
2025-07-02 06:41:17.864
2025-07-02 06:41:17.865 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.865 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.865 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.865 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.865 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.865
2025-07-02 06:41:17.865 # search for the pair that matches best without being identical
2025-07-02 06:41:17.865 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.865 # on junk -- unless we have to)
2025-07-02 06:41:17.865 for j in range(blo, bhi):
2025-07-02 06:41:17.865 bj = b[j]
2025-07-02 06:41:17.865 cruncher.set_seq2(bj)
2025-07-02 06:41:17.865 for i in range(alo, ahi):
2025-07-02 06:41:17.865 ai = a[i]
2025-07-02 06:41:17.865 if ai == bj:
2025-07-02 06:41:17.865 if eqi is None:
2025-07-02 06:41:17.865 eqi, eqj = i, j
2025-07-02 06:41:17.865 continue
2025-07-02 06:41:17.865 cruncher.set_seq1(ai)
2025-07-02 06:41:17.865 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.865 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.866 # compares by a factor of 3.
2025-07-02 06:41:17.866 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.866 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.866 # of the computation is cached by cruncher
2025-07-02 06:41:17.866 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.866 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.866 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.866 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.866 if best_ratio < cutoff:
2025-07-02 06:41:17.866 # no non-identical "pretty close" pair
2025-07-02 06:41:17.866 if eqi is None:
2025-07-02 06:41:17.866 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.866 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.866 return
2025-07-02 06:41:17.866 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.866 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.866 else:
2025-07-02 06:41:17.866 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.866 eqi = None
2025-07-02 06:41:17.866
2025-07-02 06:41:17.867 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.867 # identical
2025-07-02 06:41:17.867
2025-07-02 06:41:17.867 # pump out diffs from before the synch point
2025-07-02 06:41:17.867 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.867
2025-07-02 06:41:17.867 # do intraline marking on the synch pair
2025-07-02 06:41:17.867 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.867 if eqi is None:
2025-07-02 06:41:17.867 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.867 atags = btags = ""
2025-07-02 06:41:17.867 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.867 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.867 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.867 if tag == 'replace':
2025-07-02 06:41:17.867 atags += '^' * la
2025-07-02 06:41:17.867 btags += '^' * lb
2025-07-02 06:41:17.867 elif tag == 'delete':
2025-07-02 06:41:17.868 atags += '-' * la
2025-07-02 06:41:17.868 elif tag == 'insert':
2025-07-02 06:41:17.868 btags += '+' * lb
2025-07-02 06:41:17.868 elif tag == 'equal':
2025-07-02 06:41:17.868 atags += ' ' * la
2025-07-02 06:41:17.868 btags += ' ' * lb
2025-07-02 06:41:17.868 else:
2025-07-02 06:41:17.868 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.868 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.868 else:
2025-07-02 06:41:17.868 # the synch pair is identical
2025-07-02 06:41:17.868 yield ' ' + aelt
2025-07-02 06:41:17.868
2025-07-02 06:41:17.868 # pump out diffs from after the synch point
2025-07-02 06:41:17.868 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.868
2025-07-02 06:41:17.868 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.868 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.869
2025-07-02 06:41:17.869 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.869 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.869 alo = 303, ahi = 1101
2025-07-02 06:41:17.869 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.869 blo = 303, bhi = 1101
2025-07-02 06:41:17.869
2025-07-02 06:41:17.869 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.869 g = []
2025-07-02 06:41:17.869 if alo < ahi:
2025-07-02 06:41:17.869 if blo < bhi:
2025-07-02 06:41:17.869 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.869 else:
2025-07-02 06:41:17.869 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.869 elif blo < bhi:
2025-07-02 06:41:17.869 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.869
2025-07-02 06:41:17.869 > yield from g
2025-07-02 06:41:17.869
2025-07-02 06:41:17.870 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.870 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.870 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.870 alo = 303, ahi = 1101
2025-07-02 06:41:17.870 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.870 blo = 303, bhi = 1101
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.870 r"""
2025-07-02 06:41:17.870 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.870 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.870 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.870 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870 Example:
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870 >>> d = Differ()
2025-07-02 06:41:17.871 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.871 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.871 >>> print(''.join(results), end="")
2025-07-02 06:41:17.871 - abcDefghiJkl
2025-07-02 06:41:17.871 + abcdefGhijkl
2025-07-02 06:41:17.871 """
2025-07-02 06:41:17.871
2025-07-02 06:41:17.871 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.871 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.871 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.871 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.871 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.871
2025-07-02 06:41:17.871 # search for the pair that matches best without being identical
2025-07-02 06:41:17.871 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.871 # on junk -- unless we have to)
2025-07-02 06:41:17.871 for j in range(blo, bhi):
2025-07-02 06:41:17.871 bj = b[j]
2025-07-02 06:41:17.872 cruncher.set_seq2(bj)
2025-07-02 06:41:17.872 for i in range(alo, ahi):
2025-07-02 06:41:17.872 ai = a[i]
2025-07-02 06:41:17.872 if ai == bj:
2025-07-02 06:41:17.872 if eqi is None:
2025-07-02 06:41:17.872 eqi, eqj = i, j
2025-07-02 06:41:17.872 continue
2025-07-02 06:41:17.872 cruncher.set_seq1(ai)
2025-07-02 06:41:17.872 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.872 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.872 # compares by a factor of 3.
2025-07-02 06:41:17.872 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.872 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.872 # of the computation is cached by cruncher
2025-07-02 06:41:17.872 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.872 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.872 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.872 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.872 if best_ratio < cutoff:
2025-07-02 06:41:17.873 # no non-identical "pretty close" pair
2025-07-02 06:41:17.873 if eqi is None:
2025-07-02 06:41:17.873 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.873 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.873 return
2025-07-02 06:41:17.873 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.873 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.873 else:
2025-07-02 06:41:17.873 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.873 eqi = None
2025-07-02 06:41:17.873
2025-07-02 06:41:17.873 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.873 # identical
2025-07-02 06:41:17.873
2025-07-02 06:41:17.873 # pump out diffs from before the synch point
2025-07-02 06:41:17.873 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.873
2025-07-02 06:41:17.873 # do intraline marking on the synch pair
2025-07-02 06:41:17.873 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.874 if eqi is None:
2025-07-02 06:41:17.874 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.874 atags = btags = ""
2025-07-02 06:41:17.874 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.874 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.874 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.874 if tag == 'replace':
2025-07-02 06:41:17.874 atags += '^' * la
2025-07-02 06:41:17.874 btags += '^' * lb
2025-07-02 06:41:17.874 elif tag == 'delete':
2025-07-02 06:41:17.874 atags += '-' * la
2025-07-02 06:41:17.874 elif tag == 'insert':
2025-07-02 06:41:17.874 btags += '+' * lb
2025-07-02 06:41:17.874 elif tag == 'equal':
2025-07-02 06:41:17.874 atags += ' ' * la
2025-07-02 06:41:17.874 btags += ' ' * lb
2025-07-02 06:41:17.874 else:
2025-07-02 06:41:17.874 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.874 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.874 else:
2025-07-02 06:41:17.875 # the synch pair is identical
2025-07-02 06:41:17.875 yield ' ' + aelt
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875 # pump out diffs from after the synch point
2025-07-02 06:41:17.875 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.875 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.875 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.875 alo = 304, ahi = 1101
2025-07-02 06:41:17.875 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.875 blo = 304, bhi = 1101
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.875 g = []
2025-07-02 06:41:17.875 if alo < ahi:
2025-07-02 06:41:17.875 if blo < bhi:
2025-07-02 06:41:17.876 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.876 else:
2025-07-02 06:41:17.876 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.876 elif blo < bhi:
2025-07-02 06:41:17.876 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 > yield from g
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.876 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.876 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.876 alo = 304, ahi = 1101
2025-07-02 06:41:17.876 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.876 blo = 304, bhi = 1101
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.876 r"""
2025-07-02 06:41:17.877 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.877 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.877 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.877 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.877
2025-07-02 06:41:17.877 Example:
2025-07-02 06:41:17.877
2025-07-02 06:41:17.877 >>> d = Differ()
2025-07-02 06:41:17.877 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.877 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.877 >>> print(''.join(results), end="")
2025-07-02 06:41:17.877 - abcDefghiJkl
2025-07-02 06:41:17.877 + abcdefGhijkl
2025-07-02 06:41:17.877 """
2025-07-02 06:41:17.877
2025-07-02 06:41:17.877 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.877 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.878 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.878 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.878 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.878
2025-07-02 06:41:17.878 # search for the pair that matches best without being identical
2025-07-02 06:41:17.878 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.878 # on junk -- unless we have to)
2025-07-02 06:41:17.878 for j in range(blo, bhi):
2025-07-02 06:41:17.878 bj = b[j]
2025-07-02 06:41:17.878 cruncher.set_seq2(bj)
2025-07-02 06:41:17.878 for i in range(alo, ahi):
2025-07-02 06:41:17.878 ai = a[i]
2025-07-02 06:41:17.878 if ai == bj:
2025-07-02 06:41:17.878 if eqi is None:
2025-07-02 06:41:17.878 eqi, eqj = i, j
2025-07-02 06:41:17.878 continue
2025-07-02 06:41:17.878 cruncher.set_seq1(ai)
2025-07-02 06:41:17.878 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.878 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.879 # compares by a factor of 3.
2025-07-02 06:41:17.879 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.879 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.879 # of the computation is cached by cruncher
2025-07-02 06:41:17.879 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.879 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.879 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.879 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.879 if best_ratio < cutoff:
2025-07-02 06:41:17.879 # no non-identical "pretty close" pair
2025-07-02 06:41:17.879 if eqi is None:
2025-07-02 06:41:17.879 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.879 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.879 return
2025-07-02 06:41:17.879 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.879 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.879 else:
2025-07-02 06:41:17.879 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.879 eqi = None
2025-07-02 06:41:17.880
2025-07-02 06:41:17.880 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.880 # identical
2025-07-02 06:41:17.880
2025-07-02 06:41:17.880 # pump out diffs from before the synch point
2025-07-02 06:41:17.880 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.880
2025-07-02 06:41:17.880 # do intraline marking on the synch pair
2025-07-02 06:41:17.880 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.880 if eqi is None:
2025-07-02 06:41:17.880 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.880 atags = btags = ""
2025-07-02 06:41:17.880 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.880 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.880 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.880 if tag == 'replace':
2025-07-02 06:41:17.880 atags += '^' * la
2025-07-02 06:41:17.880 btags += '^' * lb
2025-07-02 06:41:17.880 elif tag == 'delete':
2025-07-02 06:41:17.880 atags += '-' * la
2025-07-02 06:41:17.881 elif tag == 'insert':
2025-07-02 06:41:17.881 btags += '+' * lb
2025-07-02 06:41:17.881 elif tag == 'equal':
2025-07-02 06:41:17.881 atags += ' ' * la
2025-07-02 06:41:17.881 btags += ' ' * lb
2025-07-02 06:41:17.881 else:
2025-07-02 06:41:17.881 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.881 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.881 else:
2025-07-02 06:41:17.881 # the synch pair is identical
2025-07-02 06:41:17.881 yield ' ' + aelt
2025-07-02 06:41:17.881
2025-07-02 06:41:17.881 # pump out diffs from after the synch point
2025-07-02 06:41:17.881 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.881
2025-07-02 06:41:17.881 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.881 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.881
2025-07-02 06:41:17.881 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.882 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.882 alo = 305, ahi = 1101
2025-07-02 06:41:17.882 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.882 blo = 305, bhi = 1101
2025-07-02 06:41:17.882
2025-07-02 06:41:17.882 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.882 g = []
2025-07-02 06:41:17.882 if alo < ahi:
2025-07-02 06:41:17.882 if blo < bhi:
2025-07-02 06:41:17.882 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.882 else:
2025-07-02 06:41:17.882 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.882 elif blo < bhi:
2025-07-02 06:41:17.882 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.882
2025-07-02 06:41:17.882 > yield from g
2025-07-02 06:41:17.882
2025-07-02 06:41:17.882 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.882 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.882
2025-07-02 06:41:17.883 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.883 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.883 alo = 305, ahi = 1101
2025-07-02 06:41:17.883 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.883 blo = 305, bhi = 1101
2025-07-02 06:41:17.883
2025-07-02 06:41:17.883 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.883 r"""
2025-07-02 06:41:17.883 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.883 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.883 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.883 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.883
2025-07-02 06:41:17.883 Example:
2025-07-02 06:41:17.883
2025-07-02 06:41:17.883 >>> d = Differ()
2025-07-02 06:41:17.883 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.883 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.883 >>> print(''.join(results), end="")
2025-07-02 06:41:17.884 - abcDefghiJkl
2025-07-02 06:41:17.884 + abcdefGhijkl
2025-07-02 06:41:17.884 """
2025-07-02 06:41:17.884
2025-07-02 06:41:17.884 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.884 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.884 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.884 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.884 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.884
2025-07-02 06:41:17.884 # search for the pair that matches best without being identical
2025-07-02 06:41:17.884 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.884 # on junk -- unless we have to)
2025-07-02 06:41:17.884 for j in range(blo, bhi):
2025-07-02 06:41:17.884 bj = b[j]
2025-07-02 06:41:17.884 cruncher.set_seq2(bj)
2025-07-02 06:41:17.885 for i in range(alo, ahi):
2025-07-02 06:41:17.885 ai = a[i]
2025-07-02 06:41:17.885 if ai == bj:
2025-07-02 06:41:17.885 if eqi is None:
2025-07-02 06:41:17.885 eqi, eqj = i, j
2025-07-02 06:41:17.885 continue
2025-07-02 06:41:17.885 cruncher.set_seq1(ai)
2025-07-02 06:41:17.885 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.885 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.885 # compares by a factor of 3.
2025-07-02 06:41:17.885 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.885 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.885 # of the computation is cached by cruncher
2025-07-02 06:41:17.885 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.885 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.885 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.885 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.885 if best_ratio < cutoff:
2025-07-02 06:41:17.886 # no non-identical "pretty close" pair
2025-07-02 06:41:17.886 if eqi is None:
2025-07-02 06:41:17.886 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.886 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.886 return
2025-07-02 06:41:17.886 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.886 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.886 else:
2025-07-02 06:41:17.886 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.886 eqi = None
2025-07-02 06:41:17.886
2025-07-02 06:41:17.886 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.886 # identical
2025-07-02 06:41:17.886
2025-07-02 06:41:17.886 # pump out diffs from before the synch point
2025-07-02 06:41:17.886 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.886
2025-07-02 06:41:17.886 # do intraline marking on the synch pair
2025-07-02 06:41:17.886 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.887 if eqi is None:
2025-07-02 06:41:17.887 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.887 atags = btags = ""
2025-07-02 06:41:17.887 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.887 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.887 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.887 if tag == 'replace':
2025-07-02 06:41:17.887 atags += '^' * la
2025-07-02 06:41:17.887 btags += '^' * lb
2025-07-02 06:41:17.887 elif tag == 'delete':
2025-07-02 06:41:17.887 atags += '-' * la
2025-07-02 06:41:17.887 elif tag == 'insert':
2025-07-02 06:41:17.887 btags += '+' * lb
2025-07-02 06:41:17.887 elif tag == 'equal':
2025-07-02 06:41:17.887 atags += ' ' * la
2025-07-02 06:41:17.887 btags += ' ' * lb
2025-07-02 06:41:17.887 else:
2025-07-02 06:41:17.887 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.887 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.888 else:
2025-07-02 06:41:17.888 # the synch pair is identical
2025-07-02 06:41:17.888 yield ' ' + aelt
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888 # pump out diffs from after the synch point
2025-07-02 06:41:17.888 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.888 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.888 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.888 alo = 306, ahi = 1101
2025-07-02 06:41:17.888 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.888 blo = 306, bhi = 1101
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.888 g = []
2025-07-02 06:41:17.888 if alo < ahi:
2025-07-02 06:41:17.889 if blo < bhi:
2025-07-02 06:41:17.889 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.889 else:
2025-07-02 06:41:17.889 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.889 elif blo < bhi:
2025-07-02 06:41:17.889 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 > yield from g
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.889 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.889 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.889 alo = 306, ahi = 1101
2025-07-02 06:41:17.889 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.889 blo = 306, bhi = 1101
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.889 r"""
2025-07-02 06:41:17.890 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.890 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.890 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.890 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.890
2025-07-02 06:41:17.890 Example:
2025-07-02 06:41:17.890
2025-07-02 06:41:17.890 >>> d = Differ()
2025-07-02 06:41:17.890 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.890 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.890 >>> print(''.join(results), end="")
2025-07-02 06:41:17.890 - abcDefghiJkl
2025-07-02 06:41:17.890 + abcdefGhijkl
2025-07-02 06:41:17.890 """
2025-07-02 06:41:17.890
2025-07-02 06:41:17.890 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.890 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.891 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.891 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.891 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.891
2025-07-02 06:41:17.891 # search for the pair that matches best without being identical
2025-07-02 06:41:17.891 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.891 # on junk -- unless we have to)
2025-07-02 06:41:17.891 for j in range(blo, bhi):
2025-07-02 06:41:17.891 bj = b[j]
2025-07-02 06:41:17.891 cruncher.set_seq2(bj)
2025-07-02 06:41:17.891 for i in range(alo, ahi):
2025-07-02 06:41:17.891 ai = a[i]
2025-07-02 06:41:17.891 if ai == bj:
2025-07-02 06:41:17.891 if eqi is None:
2025-07-02 06:41:17.891 eqi, eqj = i, j
2025-07-02 06:41:17.891 continue
2025-07-02 06:41:17.891 cruncher.set_seq1(ai)
2025-07-02 06:41:17.891 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.891 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.892 # compares by a factor of 3.
2025-07-02 06:41:17.892 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.892 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.892 # of the computation is cached by cruncher
2025-07-02 06:41:17.892 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.892 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.892 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.892 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.892 if best_ratio < cutoff:
2025-07-02 06:41:17.892 # no non-identical "pretty close" pair
2025-07-02 06:41:17.892 if eqi is None:
2025-07-02 06:41:17.892 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.892 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.892 return
2025-07-02 06:41:17.892 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.892 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.892 else:
2025-07-02 06:41:17.892 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.892 eqi = None
2025-07-02 06:41:17.892
2025-07-02 06:41:17.893 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.893 # identical
2025-07-02 06:41:17.893
2025-07-02 06:41:17.893 # pump out diffs from before the synch point
2025-07-02 06:41:17.893 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.893
2025-07-02 06:41:17.893 # do intraline marking on the synch pair
2025-07-02 06:41:17.893 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.893 if eqi is None:
2025-07-02 06:41:17.893 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.893 atags = btags = ""
2025-07-02 06:41:17.893 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.893 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.893 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.893 if tag == 'replace':
2025-07-02 06:41:17.893 atags += '^' * la
2025-07-02 06:41:17.893 btags += '^' * lb
2025-07-02 06:41:17.893 elif tag == 'delete':
2025-07-02 06:41:17.893 atags += '-' * la
2025-07-02 06:41:17.894 elif tag == 'insert':
2025-07-02 06:41:17.894 btags += '+' * lb
2025-07-02 06:41:17.894 elif tag == 'equal':
2025-07-02 06:41:17.894 atags += ' ' * la
2025-07-02 06:41:17.894 btags += ' ' * lb
2025-07-02 06:41:17.894 else:
2025-07-02 06:41:17.894 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.894 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.894 else:
2025-07-02 06:41:17.894 # the synch pair is identical
2025-07-02 06:41:17.894 yield ' ' + aelt
2025-07-02 06:41:17.894
2025-07-02 06:41:17.894 # pump out diffs from after the synch point
2025-07-02 06:41:17.894 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.894
2025-07-02 06:41:17.894 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.894 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.894
2025-07-02 06:41:17.894 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.895 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.895 alo = 307, ahi = 1101
2025-07-02 06:41:17.895 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.895 blo = 307, bhi = 1101
2025-07-02 06:41:17.895
2025-07-02 06:41:17.895 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.895 g = []
2025-07-02 06:41:17.895 if alo < ahi:
2025-07-02 06:41:17.895 if blo < bhi:
2025-07-02 06:41:17.895 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.895 else:
2025-07-02 06:41:17.895 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.895 elif blo < bhi:
2025-07-02 06:41:17.895 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.895
2025-07-02 06:41:17.895 > yield from g
2025-07-02 06:41:17.895
2025-07-02 06:41:17.895 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.896 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.896 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.896 alo = 307, ahi = 1101
2025-07-02 06:41:17.896 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.896 blo = 307, bhi = 1101
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.896 r"""
2025-07-02 06:41:17.896 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.896 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.896 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.896 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896 Example:
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896 >>> d = Differ()
2025-07-02 06:41:17.896 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.897 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.897 >>> print(''.join(results), end="")
2025-07-02 06:41:17.897 - abcDefghiJkl
2025-07-02 06:41:17.897 + abcdefGhijkl
2025-07-02 06:41:17.897 """
2025-07-02 06:41:17.897
2025-07-02 06:41:17.897 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.897 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.897 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.897 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.897 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.897
2025-07-02 06:41:17.897 # search for the pair that matches best without being identical
2025-07-02 06:41:17.897 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.897 # on junk -- unless we have to)
2025-07-02 06:41:17.897 for j in range(blo, bhi):
2025-07-02 06:41:17.897 bj = b[j]
2025-07-02 06:41:17.897 cruncher.set_seq2(bj)
2025-07-02 06:41:17.898 for i in range(alo, ahi):
2025-07-02 06:41:17.898 ai = a[i]
2025-07-02 06:41:17.898 if ai == bj:
2025-07-02 06:41:17.898 if eqi is None:
2025-07-02 06:41:17.898 eqi, eqj = i, j
2025-07-02 06:41:17.898 continue
2025-07-02 06:41:17.898 cruncher.set_seq1(ai)
2025-07-02 06:41:17.898 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.898 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.898 # compares by a factor of 3.
2025-07-02 06:41:17.898 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.898 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.898 # of the computation is cached by cruncher
2025-07-02 06:41:17.898 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.898 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.898 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.898 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.898 if best_ratio < cutoff:
2025-07-02 06:41:17.898 # no non-identical "pretty close" pair
2025-07-02 06:41:17.899 if eqi is None:
2025-07-02 06:41:17.899 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.899 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.899 return
2025-07-02 06:41:17.899 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.899 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.899 else:
2025-07-02 06:41:17.899 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.899 eqi = None
2025-07-02 06:41:17.899
2025-07-02 06:41:17.899 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.899 # identical
2025-07-02 06:41:17.899
2025-07-02 06:41:17.899 # pump out diffs from before the synch point
2025-07-02 06:41:17.899 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.899
2025-07-02 06:41:17.899 # do intraline marking on the synch pair
2025-07-02 06:41:17.899 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.900 if eqi is None:
2025-07-02 06:41:17.900 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.900 atags = btags = ""
2025-07-02 06:41:17.900 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.900 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.900 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.900 if tag == 'replace':
2025-07-02 06:41:17.900 atags += '^' * la
2025-07-02 06:41:17.900 btags += '^' * lb
2025-07-02 06:41:17.900 elif tag == 'delete':
2025-07-02 06:41:17.900 atags += '-' * la
2025-07-02 06:41:17.900 elif tag == 'insert':
2025-07-02 06:41:17.900 btags += '+' * lb
2025-07-02 06:41:17.900 elif tag == 'equal':
2025-07-02 06:41:17.900 atags += ' ' * la
2025-07-02 06:41:17.900 btags += ' ' * lb
2025-07-02 06:41:17.900 else:
2025-07-02 06:41:17.900 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.901 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.901 else:
2025-07-02 06:41:17.901 # the synch pair is identical
2025-07-02 06:41:17.901 yield ' ' + aelt
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901 # pump out diffs from after the synch point
2025-07-02 06:41:17.901 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.901 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.901 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.901 alo = 308, ahi = 1101
2025-07-02 06:41:17.901 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.901 blo = 308, bhi = 1101
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.902 g = []
2025-07-02 06:41:17.902 if alo < ahi:
2025-07-02 06:41:17.902 if blo < bhi:
2025-07-02 06:41:17.902 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.902 else:
2025-07-02 06:41:17.902 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.902 elif blo < bhi:
2025-07-02 06:41:17.902 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.902
2025-07-02 06:41:17.902 > yield from g
2025-07-02 06:41:17.902
2025-07-02 06:41:17.902 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.902 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.902
2025-07-02 06:41:17.902 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.902 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.902 alo = 308, ahi = 1101
2025-07-02 06:41:17.903 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.903 blo = 308, bhi = 1101
2025-07-02 06:41:17.903
2025-07-02 06:41:17.903 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.903 r"""
2025-07-02 06:41:17.903 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.903 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.903 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.903 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.903
2025-07-02 06:41:17.903 Example:
2025-07-02 06:41:17.903
2025-07-02 06:41:17.903 >>> d = Differ()
2025-07-02 06:41:17.903 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.903 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.903 >>> print(''.join(results), end="")
2025-07-02 06:41:17.903 - abcDefghiJkl
2025-07-02 06:41:17.904 + abcdefGhijkl
2025-07-02 06:41:17.904 """
2025-07-02 06:41:17.904
2025-07-02 06:41:17.904 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.904 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.904 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.904 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.904 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.904
2025-07-02 06:41:17.904 # search for the pair that matches best without being identical
2025-07-02 06:41:17.904 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.904 # on junk -- unless we have to)
2025-07-02 06:41:17.904 for j in range(blo, bhi):
2025-07-02 06:41:17.904 bj = b[j]
2025-07-02 06:41:17.904 cruncher.set_seq2(bj)
2025-07-02 06:41:17.904 for i in range(alo, ahi):
2025-07-02 06:41:17.904 ai = a[i]
2025-07-02 06:41:17.905 if ai == bj:
2025-07-02 06:41:17.905 if eqi is None:
2025-07-02 06:41:17.905 eqi, eqj = i, j
2025-07-02 06:41:17.905 continue
2025-07-02 06:41:17.905 cruncher.set_seq1(ai)
2025-07-02 06:41:17.905 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.905 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.905 # compares by a factor of 3.
2025-07-02 06:41:17.905 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.905 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.905 # of the computation is cached by cruncher
2025-07-02 06:41:17.905 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.905 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.905 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.905 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.905 if best_ratio < cutoff:
2025-07-02 06:41:17.905 # no non-identical "pretty close" pair
2025-07-02 06:41:17.905 if eqi is None:
2025-07-02 06:41:17.906 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.906 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.906 return
2025-07-02 06:41:17.906 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.906 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.906 else:
2025-07-02 06:41:17.906 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.906 eqi = None
2025-07-02 06:41:17.906
2025-07-02 06:41:17.906 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.906 # identical
2025-07-02 06:41:17.906
2025-07-02 06:41:17.906 # pump out diffs from before the synch point
2025-07-02 06:41:17.906 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.906
2025-07-02 06:41:17.906 # do intraline marking on the synch pair
2025-07-02 06:41:17.906 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.906 if eqi is None:
2025-07-02 06:41:17.906 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.907 atags = btags = ""
2025-07-02 06:41:17.907 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.907 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.907 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.907 if tag == 'replace':
2025-07-02 06:41:17.907 atags += '^' * la
2025-07-02 06:41:17.907 btags += '^' * lb
2025-07-02 06:41:17.907 elif tag == 'delete':
2025-07-02 06:41:17.907 atags += '-' * la
2025-07-02 06:41:17.907 elif tag == 'insert':
2025-07-02 06:41:17.907 btags += '+' * lb
2025-07-02 06:41:17.907 elif tag == 'equal':
2025-07-02 06:41:17.907 atags += ' ' * la
2025-07-02 06:41:17.907 btags += ' ' * lb
2025-07-02 06:41:17.907 else:
2025-07-02 06:41:17.907 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.907 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.907 else:
2025-07-02 06:41:17.907 # the synch pair is identical
2025-07-02 06:41:17.908 yield ' ' + aelt
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908 # pump out diffs from after the synch point
2025-07-02 06:41:17.908 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.908 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.908 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.908 alo = 309, ahi = 1101
2025-07-02 06:41:17.908 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.908 blo = 309, bhi = 1101
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.908 g = []
2025-07-02 06:41:17.908 if alo < ahi:
2025-07-02 06:41:17.908 if blo < bhi:
2025-07-02 06:41:17.909 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.909 else:
2025-07-02 06:41:17.909 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.909 elif blo < bhi:
2025-07-02 06:41:17.909 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 > yield from g
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.909 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.909 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.909 alo = 309, ahi = 1101
2025-07-02 06:41:17.909 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.909 blo = 309, bhi = 1101
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.909 r"""
2025-07-02 06:41:17.910 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.910 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.910 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.910 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.910
2025-07-02 06:41:17.910 Example:
2025-07-02 06:41:17.910
2025-07-02 06:41:17.910 >>> d = Differ()
2025-07-02 06:41:17.910 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.910 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.910 >>> print(''.join(results), end="")
2025-07-02 06:41:17.910 - abcDefghiJkl
2025-07-02 06:41:17.910 + abcdefGhijkl
2025-07-02 06:41:17.910 """
2025-07-02 06:41:17.910
2025-07-02 06:41:17.910 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.911 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.911 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.911 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.911 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.911
2025-07-02 06:41:17.911 # search for the pair that matches best without being identical
2025-07-02 06:41:17.911 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.911 # on junk -- unless we have to)
2025-07-02 06:41:17.911 for j in range(blo, bhi):
2025-07-02 06:41:17.911 bj = b[j]
2025-07-02 06:41:17.911 cruncher.set_seq2(bj)
2025-07-02 06:41:17.911 for i in range(alo, ahi):
2025-07-02 06:41:17.911 ai = a[i]
2025-07-02 06:41:17.911 if ai == bj:
2025-07-02 06:41:17.911 if eqi is None:
2025-07-02 06:41:17.911 eqi, eqj = i, j
2025-07-02 06:41:17.911 continue
2025-07-02 06:41:17.911 cruncher.set_seq1(ai)
2025-07-02 06:41:17.911 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.912 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.912 # compares by a factor of 3.
2025-07-02 06:41:17.912 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.912 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.912 # of the computation is cached by cruncher
2025-07-02 06:41:17.912 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.912 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.912 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.912 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.912 if best_ratio < cutoff:
2025-07-02 06:41:17.912 # no non-identical "pretty close" pair
2025-07-02 06:41:17.912 if eqi is None:
2025-07-02 06:41:17.912 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.912 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.912 return
2025-07-02 06:41:17.912 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.912 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.912 else:
2025-07-02 06:41:17.913 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.913 eqi = None
2025-07-02 06:41:17.913
2025-07-02 06:41:17.913 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.913 # identical
2025-07-02 06:41:17.913
2025-07-02 06:41:17.913 # pump out diffs from before the synch point
2025-07-02 06:41:17.913 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.913
2025-07-02 06:41:17.913 # do intraline marking on the synch pair
2025-07-02 06:41:17.913 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.913 if eqi is None:
2025-07-02 06:41:17.913 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.913 atags = btags = ""
2025-07-02 06:41:17.913 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.913 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.913 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.913 if tag == 'replace':
2025-07-02 06:41:17.914 atags += '^' * la
2025-07-02 06:41:17.914 btags += '^' * lb
2025-07-02 06:41:17.914 elif tag == 'delete':
2025-07-02 06:41:17.914 atags += '-' * la
2025-07-02 06:41:17.914 elif tag == 'insert':
2025-07-02 06:41:17.914 btags += '+' * lb
2025-07-02 06:41:17.914 elif tag == 'equal':
2025-07-02 06:41:17.914 atags += ' ' * la
2025-07-02 06:41:17.914 btags += ' ' * lb
2025-07-02 06:41:17.914 else:
2025-07-02 06:41:17.914 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.914 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.914 else:
2025-07-02 06:41:17.914 # the synch pair is identical
2025-07-02 06:41:17.914 yield ' ' + aelt
2025-07-02 06:41:17.914
2025-07-02 06:41:17.914 # pump out diffs from after the synch point
2025-07-02 06:41:17.914 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.914
2025-07-02 06:41:17.915 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.915 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.915
2025-07-02 06:41:17.915 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.915 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.915 alo = 312, ahi = 1101
2025-07-02 06:41:17.915 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.915 blo = 312, bhi = 1101
2025-07-02 06:41:17.915
2025-07-02 06:41:17.915 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.915 g = []
2025-07-02 06:41:17.915 if alo < ahi:
2025-07-02 06:41:17.915 if blo < bhi:
2025-07-02 06:41:17.915 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.915 else:
2025-07-02 06:41:17.915 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.915 elif blo < bhi:
2025-07-02 06:41:17.916 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 > yield from g
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.916 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.916 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.916 alo = 312, ahi = 1101
2025-07-02 06:41:17.916 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.916 blo = 312, bhi = 1101
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.916 r"""
2025-07-02 06:41:17.916 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.916 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.916 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.917 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.917
2025-07-02 06:41:17.917 Example:
2025-07-02 06:41:17.917
2025-07-02 06:41:17.917 >>> d = Differ()
2025-07-02 06:41:17.917 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.917 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.917 >>> print(''.join(results), end="")
2025-07-02 06:41:17.917 - abcDefghiJkl
2025-07-02 06:41:17.917 + abcdefGhijkl
2025-07-02 06:41:17.917 """
2025-07-02 06:41:17.917
2025-07-02 06:41:17.917 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.917 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.917 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.917 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.917 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.918
2025-07-02 06:41:17.918 # search for the pair that matches best without being identical
2025-07-02 06:41:17.918 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.918 # on junk -- unless we have to)
2025-07-02 06:41:17.918 for j in range(blo, bhi):
2025-07-02 06:41:17.918 bj = b[j]
2025-07-02 06:41:17.918 cruncher.set_seq2(bj)
2025-07-02 06:41:17.918 for i in range(alo, ahi):
2025-07-02 06:41:17.918 ai = a[i]
2025-07-02 06:41:17.918 if ai == bj:
2025-07-02 06:41:17.918 if eqi is None:
2025-07-02 06:41:17.918 eqi, eqj = i, j
2025-07-02 06:41:17.918 continue
2025-07-02 06:41:17.918 cruncher.set_seq1(ai)
2025-07-02 06:41:17.918 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.918 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.918 # compares by a factor of 3.
2025-07-02 06:41:17.918 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.919 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.919 # of the computation is cached by cruncher
2025-07-02 06:41:17.919 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.919 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.919 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.919 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.919 if best_ratio < cutoff:
2025-07-02 06:41:17.919 # no non-identical "pretty close" pair
2025-07-02 06:41:17.919 if eqi is None:
2025-07-02 06:41:17.919 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.919 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.919 return
2025-07-02 06:41:17.919 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.919 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.919 else:
2025-07-02 06:41:17.919 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.919 eqi = None
2025-07-02 06:41:17.919
2025-07-02 06:41:17.919 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.920 # identical
2025-07-02 06:41:17.920
2025-07-02 06:41:17.920 # pump out diffs from before the synch point
2025-07-02 06:41:17.920 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.920
2025-07-02 06:41:17.920 # do intraline marking on the synch pair
2025-07-02 06:41:17.920 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.920 if eqi is None:
2025-07-02 06:41:17.920 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.920 atags = btags = ""
2025-07-02 06:41:17.920 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.920 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.920 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.920 if tag == 'replace':
2025-07-02 06:41:17.920 atags += '^' * la
2025-07-02 06:41:17.920 btags += '^' * lb
2025-07-02 06:41:17.920 elif tag == 'delete':
2025-07-02 06:41:17.920 atags += '-' * la
2025-07-02 06:41:17.920 elif tag == 'insert':
2025-07-02 06:41:17.921 btags += '+' * lb
2025-07-02 06:41:17.921 elif tag == 'equal':
2025-07-02 06:41:17.921 atags += ' ' * la
2025-07-02 06:41:17.921 btags += ' ' * lb
2025-07-02 06:41:17.921 else:
2025-07-02 06:41:17.921 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.921 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.921 else:
2025-07-02 06:41:17.921 # the synch pair is identical
2025-07-02 06:41:17.921 yield ' ' + aelt
2025-07-02 06:41:17.921
2025-07-02 06:41:17.921 # pump out diffs from after the synch point
2025-07-02 06:41:17.921 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.921
2025-07-02 06:41:17.921 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.921 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.921
2025-07-02 06:41:17.921 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.922 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.922 alo = 313, ahi = 1101
2025-07-02 06:41:17.922 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.922 blo = 313, bhi = 1101
2025-07-02 06:41:17.922
2025-07-02 06:41:17.922 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.922 g = []
2025-07-02 06:41:17.922 if alo < ahi:
2025-07-02 06:41:17.922 if blo < bhi:
2025-07-02 06:41:17.922 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.922 else:
2025-07-02 06:41:17.922 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.922 elif blo < bhi:
2025-07-02 06:41:17.922 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.922
2025-07-02 06:41:17.922 > yield from g
2025-07-02 06:41:17.922
2025-07-02 06:41:17.922 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.923 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.923 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.923 alo = 313, ahi = 1101
2025-07-02 06:41:17.923 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.923 blo = 313, bhi = 1101
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.923 r"""
2025-07-02 06:41:17.923 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.923 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.923 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.923 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923 Example:
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923 >>> d = Differ()
2025-07-02 06:41:17.924 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.924 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.924 >>> print(''.join(results), end="")
2025-07-02 06:41:17.924 - abcDefghiJkl
2025-07-02 06:41:17.924 + abcdefGhijkl
2025-07-02 06:41:17.924 """
2025-07-02 06:41:17.924
2025-07-02 06:41:17.924 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.924 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.924 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.924 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.924 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.924
2025-07-02 06:41:17.924 # search for the pair that matches best without being identical
2025-07-02 06:41:17.924 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.924 # on junk -- unless we have to)
2025-07-02 06:41:17.924 for j in range(blo, bhi):
2025-07-02 06:41:17.925 bj = b[j]
2025-07-02 06:41:17.925 cruncher.set_seq2(bj)
2025-07-02 06:41:17.925 for i in range(alo, ahi):
2025-07-02 06:41:17.925 ai = a[i]
2025-07-02 06:41:17.925 if ai == bj:
2025-07-02 06:41:17.925 if eqi is None:
2025-07-02 06:41:17.925 eqi, eqj = i, j
2025-07-02 06:41:17.925 continue
2025-07-02 06:41:17.925 cruncher.set_seq1(ai)
2025-07-02 06:41:17.925 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.925 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.925 # compares by a factor of 3.
2025-07-02 06:41:17.925 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.925 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.925 # of the computation is cached by cruncher
2025-07-02 06:41:17.925 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.925 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.925 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.925 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.925 if best_ratio < cutoff:
2025-07-02 06:41:17.926 # no non-identical "pretty close" pair
2025-07-02 06:41:17.926 if eqi is None:
2025-07-02 06:41:17.926 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.926 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.926 return
2025-07-02 06:41:17.926 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.926 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.926 else:
2025-07-02 06:41:17.926 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.926 eqi = None
2025-07-02 06:41:17.926
2025-07-02 06:41:17.926 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.926 # identical
2025-07-02 06:41:17.926
2025-07-02 06:41:17.926 # pump out diffs from before the synch point
2025-07-02 06:41:17.926 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.926
2025-07-02 06:41:17.926 # do intraline marking on the synch pair
2025-07-02 06:41:17.926 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.927 if eqi is None:
2025-07-02 06:41:17.927 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.927 atags = btags = ""
2025-07-02 06:41:17.927 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.927 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.927 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.927 if tag == 'replace':
2025-07-02 06:41:17.927 atags += '^' * la
2025-07-02 06:41:17.927 btags += '^' * lb
2025-07-02 06:41:17.927 elif tag == 'delete':
2025-07-02 06:41:17.927 atags += '-' * la
2025-07-02 06:41:17.927 elif tag == 'insert':
2025-07-02 06:41:17.927 btags += '+' * lb
2025-07-02 06:41:17.927 elif tag == 'equal':
2025-07-02 06:41:17.927 atags += ' ' * la
2025-07-02 06:41:17.927 btags += ' ' * lb
2025-07-02 06:41:17.927 else:
2025-07-02 06:41:17.927 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.927 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.927 else:
2025-07-02 06:41:17.928 # the synch pair is identical
2025-07-02 06:41:17.928 yield ' ' + aelt
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928 # pump out diffs from after the synch point
2025-07-02 06:41:17.928 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.928 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.928 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.928 alo = 314, ahi = 1101
2025-07-02 06:41:17.928 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.928 blo = 314, bhi = 1101
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.928 g = []
2025-07-02 06:41:17.928 if alo < ahi:
2025-07-02 06:41:17.928 if blo < bhi:
2025-07-02 06:41:17.929 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.929 else:
2025-07-02 06:41:17.929 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.929 elif blo < bhi:
2025-07-02 06:41:17.929 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 > yield from g
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.929 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.929 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.929 alo = 314, ahi = 1101
2025-07-02 06:41:17.929 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.929 blo = 314, bhi = 1101
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.929 r"""
2025-07-02 06:41:17.930 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.930 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.930 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.930 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.930
2025-07-02 06:41:17.930 Example:
2025-07-02 06:41:17.930
2025-07-02 06:41:17.930 >>> d = Differ()
2025-07-02 06:41:17.930 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.930 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.930 >>> print(''.join(results), end="")
2025-07-02 06:41:17.930 - abcDefghiJkl
2025-07-02 06:41:17.930 + abcdefGhijkl
2025-07-02 06:41:17.930 """
2025-07-02 06:41:17.930
2025-07-02 06:41:17.930 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.930 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.930 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.931 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.931 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.931
2025-07-02 06:41:17.931 # search for the pair that matches best without being identical
2025-07-02 06:41:17.931 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.931 # on junk -- unless we have to)
2025-07-02 06:41:17.931 for j in range(blo, bhi):
2025-07-02 06:41:17.931 bj = b[j]
2025-07-02 06:41:17.931 cruncher.set_seq2(bj)
2025-07-02 06:41:17.931 for i in range(alo, ahi):
2025-07-02 06:41:17.931 ai = a[i]
2025-07-02 06:41:17.931 if ai == bj:
2025-07-02 06:41:17.931 if eqi is None:
2025-07-02 06:41:17.931 eqi, eqj = i, j
2025-07-02 06:41:17.931 continue
2025-07-02 06:41:17.931 cruncher.set_seq1(ai)
2025-07-02 06:41:17.931 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.931 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.932 # compares by a factor of 3.
2025-07-02 06:41:17.932 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.932 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.932 # of the computation is cached by cruncher
2025-07-02 06:41:17.932 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.932 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.932 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.932 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.932 if best_ratio < cutoff:
2025-07-02 06:41:17.932 # no non-identical "pretty close" pair
2025-07-02 06:41:17.932 if eqi is None:
2025-07-02 06:41:17.932 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.932 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.932 return
2025-07-02 06:41:17.932 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.932 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.932 else:
2025-07-02 06:41:17.932 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.933 eqi = None
2025-07-02 06:41:17.933
2025-07-02 06:41:17.933 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.933 # identical
2025-07-02 06:41:17.933
2025-07-02 06:41:17.933 # pump out diffs from before the synch point
2025-07-02 06:41:17.933 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.933
2025-07-02 06:41:17.933 # do intraline marking on the synch pair
2025-07-02 06:41:17.933 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.933 if eqi is None:
2025-07-02 06:41:17.933 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.933 atags = btags = ""
2025-07-02 06:41:17.933 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.933 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.933 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.933 if tag == 'replace':
2025-07-02 06:41:17.933 atags += '^' * la
2025-07-02 06:41:17.933 btags += '^' * lb
2025-07-02 06:41:17.934 elif tag == 'delete':
2025-07-02 06:41:17.934 atags += '-' * la
2025-07-02 06:41:17.934 elif tag == 'insert':
2025-07-02 06:41:17.934 btags += '+' * lb
2025-07-02 06:41:17.934 elif tag == 'equal':
2025-07-02 06:41:17.934 atags += ' ' * la
2025-07-02 06:41:17.934 btags += ' ' * lb
2025-07-02 06:41:17.934 else:
2025-07-02 06:41:17.934 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.934 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.934 else:
2025-07-02 06:41:17.934 # the synch pair is identical
2025-07-02 06:41:17.934 yield ' ' + aelt
2025-07-02 06:41:17.934
2025-07-02 06:41:17.934 # pump out diffs from after the synch point
2025-07-02 06:41:17.934 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.934
2025-07-02 06:41:17.934 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.934 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.934
2025-07-02 06:41:17.935 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.935 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.935 alo = 315, ahi = 1101
2025-07-02 06:41:17.935 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.935 blo = 315, bhi = 1101
2025-07-02 06:41:17.935
2025-07-02 06:41:17.935 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.935 g = []
2025-07-02 06:41:17.935 if alo < ahi:
2025-07-02 06:41:17.935 if blo < bhi:
2025-07-02 06:41:17.935 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.935 else:
2025-07-02 06:41:17.935 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.935 elif blo < bhi:
2025-07-02 06:41:17.935 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.935
2025-07-02 06:41:17.935 > yield from g
2025-07-02 06:41:17.935
2025-07-02 06:41:17.935 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.936 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.936 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.936 alo = 315, ahi = 1101
2025-07-02 06:41:17.936 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.936 blo = 315, bhi = 1101
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.936 r"""
2025-07-02 06:41:17.936 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.936 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.936 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.936 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936 Example:
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936 >>> d = Differ()
2025-07-02 06:41:17.937 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.937 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.937 >>> print(''.join(results), end="")
2025-07-02 06:41:17.937 - abcDefghiJkl
2025-07-02 06:41:17.937 + abcdefGhijkl
2025-07-02 06:41:17.937 """
2025-07-02 06:41:17.937
2025-07-02 06:41:17.937 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.937 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.937 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.937 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.937 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.937
2025-07-02 06:41:17.937 # search for the pair that matches best without being identical
2025-07-02 06:41:17.937 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.937 # on junk -- unless we have to)
2025-07-02 06:41:17.937 for j in range(blo, bhi):
2025-07-02 06:41:17.937 bj = b[j]
2025-07-02 06:41:17.938 cruncher.set_seq2(bj)
2025-07-02 06:41:17.938 for i in range(alo, ahi):
2025-07-02 06:41:17.938 ai = a[i]
2025-07-02 06:41:17.938 if ai == bj:
2025-07-02 06:41:17.938 if eqi is None:
2025-07-02 06:41:17.938 eqi, eqj = i, j
2025-07-02 06:41:17.938 continue
2025-07-02 06:41:17.938 cruncher.set_seq1(ai)
2025-07-02 06:41:17.938 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.938 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.938 # compares by a factor of 3.
2025-07-02 06:41:17.938 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.938 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.938 # of the computation is cached by cruncher
2025-07-02 06:41:17.938 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.938 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.938 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.938 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.938 if best_ratio < cutoff:
2025-07-02 06:41:17.938 # no non-identical "pretty close" pair
2025-07-02 06:41:17.939 if eqi is None:
2025-07-02 06:41:17.939 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.939 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.939 return
2025-07-02 06:41:17.939 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.939 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.939 else:
2025-07-02 06:41:17.939 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.939 eqi = None
2025-07-02 06:41:17.939
2025-07-02 06:41:17.939 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.939 # identical
2025-07-02 06:41:17.939
2025-07-02 06:41:17.939 # pump out diffs from before the synch point
2025-07-02 06:41:17.939 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.939
2025-07-02 06:41:17.939 # do intraline marking on the synch pair
2025-07-02 06:41:17.939 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.940 if eqi is None:
2025-07-02 06:41:17.940 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.940 atags = btags = ""
2025-07-02 06:41:17.940 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.940 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.940 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.940 if tag == 'replace':
2025-07-02 06:41:17.940 atags += '^' * la
2025-07-02 06:41:17.940 btags += '^' * lb
2025-07-02 06:41:17.940 elif tag == 'delete':
2025-07-02 06:41:17.940 atags += '-' * la
2025-07-02 06:41:17.940 elif tag == 'insert':
2025-07-02 06:41:17.940 btags += '+' * lb
2025-07-02 06:41:17.940 elif tag == 'equal':
2025-07-02 06:41:17.940 atags += ' ' * la
2025-07-02 06:41:17.940 btags += ' ' * lb
2025-07-02 06:41:17.940 else:
2025-07-02 06:41:17.940 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.940 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.941 else:
2025-07-02 06:41:17.941 # the synch pair is identical
2025-07-02 06:41:17.941 yield ' ' + aelt
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941 # pump out diffs from after the synch point
2025-07-02 06:41:17.941 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.941 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.941 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.941 alo = 316, ahi = 1101
2025-07-02 06:41:17.941 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.941 blo = 316, bhi = 1101
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.941 g = []
2025-07-02 06:41:17.941 if alo < ahi:
2025-07-02 06:41:17.942 if blo < bhi:
2025-07-02 06:41:17.942 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.942 else:
2025-07-02 06:41:17.942 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.942 elif blo < bhi:
2025-07-02 06:41:17.942 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 > yield from g
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.942 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.942 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.942 alo = 316, ahi = 1101
2025-07-02 06:41:17.942 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.942 blo = 316, bhi = 1101
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.943 r"""
2025-07-02 06:41:17.943 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.943 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.943 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.943 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.943
2025-07-02 06:41:17.943 Example:
2025-07-02 06:41:17.943
2025-07-02 06:41:17.943 >>> d = Differ()
2025-07-02 06:41:17.943 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.943 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.943 >>> print(''.join(results), end="")
2025-07-02 06:41:17.943 - abcDefghiJkl
2025-07-02 06:41:17.943 + abcdefGhijkl
2025-07-02 06:41:17.943 """
2025-07-02 06:41:17.943
2025-07-02 06:41:17.943 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.944 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.944 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.944 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.944 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.944
2025-07-02 06:41:17.944 # search for the pair that matches best without being identical
2025-07-02 06:41:17.944 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.944 # on junk -- unless we have to)
2025-07-02 06:41:17.944 for j in range(blo, bhi):
2025-07-02 06:41:17.944 bj = b[j]
2025-07-02 06:41:17.944 cruncher.set_seq2(bj)
2025-07-02 06:41:17.944 for i in range(alo, ahi):
2025-07-02 06:41:17.944 ai = a[i]
2025-07-02 06:41:17.944 if ai == bj:
2025-07-02 06:41:17.944 if eqi is None:
2025-07-02 06:41:17.944 eqi, eqj = i, j
2025-07-02 06:41:17.944 continue
2025-07-02 06:41:17.944 cruncher.set_seq1(ai)
2025-07-02 06:41:17.944 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.944 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.945 # compares by a factor of 3.
2025-07-02 06:41:17.945 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.945 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.945 # of the computation is cached by cruncher
2025-07-02 06:41:17.945 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.945 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.945 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.945 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.945 if best_ratio < cutoff:
2025-07-02 06:41:17.945 # no non-identical "pretty close" pair
2025-07-02 06:41:17.945 if eqi is None:
2025-07-02 06:41:17.945 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.945 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.945 return
2025-07-02 06:41:17.945 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.945 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.945 else:
2025-07-02 06:41:17.945 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.945 eqi = None
2025-07-02 06:41:17.946
2025-07-02 06:41:17.946 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.946 # identical
2025-07-02 06:41:17.946
2025-07-02 06:41:17.946 # pump out diffs from before the synch point
2025-07-02 06:41:17.946 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.946
2025-07-02 06:41:17.946 # do intraline marking on the synch pair
2025-07-02 06:41:17.946 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.946 if eqi is None:
2025-07-02 06:41:17.946 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.946 atags = btags = ""
2025-07-02 06:41:17.946 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.946 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.946 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.946 if tag == 'replace':
2025-07-02 06:41:17.946 atags += '^' * la
2025-07-02 06:41:17.946 btags += '^' * lb
2025-07-02 06:41:17.946 elif tag == 'delete':
2025-07-02 06:41:17.946 atags += '-' * la
2025-07-02 06:41:17.947 elif tag == 'insert':
2025-07-02 06:41:17.947 btags += '+' * lb
2025-07-02 06:41:17.947 elif tag == 'equal':
2025-07-02 06:41:17.947 atags += ' ' * la
2025-07-02 06:41:17.947 btags += ' ' * lb
2025-07-02 06:41:17.947 else:
2025-07-02 06:41:17.947 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.947 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.947 else:
2025-07-02 06:41:17.947 # the synch pair is identical
2025-07-02 06:41:17.947 yield ' ' + aelt
2025-07-02 06:41:17.947
2025-07-02 06:41:17.947 # pump out diffs from after the synch point
2025-07-02 06:41:17.947 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.947
2025-07-02 06:41:17.947 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.947 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.948
2025-07-02 06:41:17.948 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.948 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.948 alo = 317, ahi = 1101
2025-07-02 06:41:17.948 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.948 blo = 317, bhi = 1101
2025-07-02 06:41:17.948
2025-07-02 06:41:17.948 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.948 g = []
2025-07-02 06:41:17.948 if alo < ahi:
2025-07-02 06:41:17.948 if blo < bhi:
2025-07-02 06:41:17.948 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.948 else:
2025-07-02 06:41:17.948 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.948 elif blo < bhi:
2025-07-02 06:41:17.948 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.948
2025-07-02 06:41:17.948 > yield from g
2025-07-02 06:41:17.949
2025-07-02 06:41:17.949 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.949 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.949
2025-07-02 06:41:17.949 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.949 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.949 alo = 317, ahi = 1101
2025-07-02 06:41:17.949 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.949 blo = 317, bhi = 1101
2025-07-02 06:41:17.949
2025-07-02 06:41:17.949 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.949 r"""
2025-07-02 06:41:17.949 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.949 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.949 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.949 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.949
2025-07-02 06:41:17.950 Example:
2025-07-02 06:41:17.950
2025-07-02 06:41:17.950 >>> d = Differ()
2025-07-02 06:41:17.950 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.950 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.950 >>> print(''.join(results), end="")
2025-07-02 06:41:17.950 - abcDefghiJkl
2025-07-02 06:41:17.950 + abcdefGhijkl
2025-07-02 06:41:17.950 """
2025-07-02 06:41:17.950
2025-07-02 06:41:17.950 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.950 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.950 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.950 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.950 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.950
2025-07-02 06:41:17.950 # search for the pair that matches best without being identical
2025-07-02 06:41:17.951 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.951 # on junk -- unless we have to)
2025-07-02 06:41:17.951 for j in range(blo, bhi):
2025-07-02 06:41:17.951 bj = b[j]
2025-07-02 06:41:17.951 cruncher.set_seq2(bj)
2025-07-02 06:41:17.951 for i in range(alo, ahi):
2025-07-02 06:41:17.951 ai = a[i]
2025-07-02 06:41:17.951 if ai == bj:
2025-07-02 06:41:17.951 if eqi is None:
2025-07-02 06:41:17.951 eqi, eqj = i, j
2025-07-02 06:41:17.951 continue
2025-07-02 06:41:17.951 cruncher.set_seq1(ai)
2025-07-02 06:41:17.951 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.951 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.951 # compares by a factor of 3.
2025-07-02 06:41:17.951 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.951 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.951 # of the computation is cached by cruncher
2025-07-02 06:41:17.951 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.952 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.952 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.952 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.952 if best_ratio < cutoff:
2025-07-02 06:41:17.952 # no non-identical "pretty close" pair
2025-07-02 06:41:17.952 if eqi is None:
2025-07-02 06:41:17.952 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.952 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.952 return
2025-07-02 06:41:17.952 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.952 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.952 else:
2025-07-02 06:41:17.952 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.952 eqi = None
2025-07-02 06:41:17.952
2025-07-02 06:41:17.952 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.952 # identical
2025-07-02 06:41:17.952
2025-07-02 06:41:17.952 # pump out diffs from before the synch point
2025-07-02 06:41:17.952 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.953
2025-07-02 06:41:17.953 # do intraline marking on the synch pair
2025-07-02 06:41:17.953 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.953 if eqi is None:
2025-07-02 06:41:17.953 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.953 atags = btags = ""
2025-07-02 06:41:17.953 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.953 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.953 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.953 if tag == 'replace':
2025-07-02 06:41:17.953 atags += '^' * la
2025-07-02 06:41:17.953 btags += '^' * lb
2025-07-02 06:41:17.953 elif tag == 'delete':
2025-07-02 06:41:17.953 atags += '-' * la
2025-07-02 06:41:17.953 elif tag == 'insert':
2025-07-02 06:41:17.953 btags += '+' * lb
2025-07-02 06:41:17.953 elif tag == 'equal':
2025-07-02 06:41:17.953 atags += ' ' * la
2025-07-02 06:41:17.953 btags += ' ' * lb
2025-07-02 06:41:17.954 else:
2025-07-02 06:41:17.954 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.954 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.954 else:
2025-07-02 06:41:17.954 # the synch pair is identical
2025-07-02 06:41:17.954 yield ' ' + aelt
2025-07-02 06:41:17.954
2025-07-02 06:41:17.954 # pump out diffs from after the synch point
2025-07-02 06:41:17.954 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.954
2025-07-02 06:41:17.954 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.954 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.954
2025-07-02 06:41:17.954 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.954 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.954 alo = 318, ahi = 1101
2025-07-02 06:41:17.954 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.954 blo = 318, bhi = 1101
2025-07-02 06:41:17.954
2025-07-02 06:41:17.955 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.955 g = []
2025-07-02 06:41:17.955 if alo < ahi:
2025-07-02 06:41:17.955 if blo < bhi:
2025-07-02 06:41:17.955 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.955 else:
2025-07-02 06:41:17.955 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.955 elif blo < bhi:
2025-07-02 06:41:17.955 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.955
2025-07-02 06:41:17.955 > yield from g
2025-07-02 06:41:17.955
2025-07-02 06:41:17.955 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.955 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.955
2025-07-02 06:41:17.955 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.955 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.955 alo = 318, ahi = 1101
2025-07-02 06:41:17.955 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.955 blo = 318, bhi = 1101
2025-07-02 06:41:17.956
2025-07-02 06:41:17.956 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.956 r"""
2025-07-02 06:41:17.956 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.956 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.956 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.956 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.956
2025-07-02 06:41:17.956 Example:
2025-07-02 06:41:17.956
2025-07-02 06:41:17.956 >>> d = Differ()
2025-07-02 06:41:17.956 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.956 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.956 >>> print(''.join(results), end="")
2025-07-02 06:41:17.956 - abcDefghiJkl
2025-07-02 06:41:17.956 + abcdefGhijkl
2025-07-02 06:41:17.956 """
2025-07-02 06:41:17.957
2025-07-02 06:41:17.957 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.957 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.957 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.957 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.957 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.957
2025-07-02 06:41:17.957 # search for the pair that matches best without being identical
2025-07-02 06:41:17.957 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.957 # on junk -- unless we have to)
2025-07-02 06:41:17.957 for j in range(blo, bhi):
2025-07-02 06:41:17.957 bj = b[j]
2025-07-02 06:41:17.957 cruncher.set_seq2(bj)
2025-07-02 06:41:17.957 for i in range(alo, ahi):
2025-07-02 06:41:17.957 ai = a[i]
2025-07-02 06:41:17.957 if ai == bj:
2025-07-02 06:41:17.957 if eqi is None:
2025-07-02 06:41:17.957 eqi, eqj = i, j
2025-07-02 06:41:17.957 continue
2025-07-02 06:41:17.957 cruncher.set_seq1(ai)
2025-07-02 06:41:17.958 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.958 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.958 # compares by a factor of 3.
2025-07-02 06:41:17.958 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.958 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.958 # of the computation is cached by cruncher
2025-07-02 06:41:17.958 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.958 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.958 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.958 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.958 if best_ratio < cutoff:
2025-07-02 06:41:17.958 # no non-identical "pretty close" pair
2025-07-02 06:41:17.958 if eqi is None:
2025-07-02 06:41:17.958 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.958 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.958 return
2025-07-02 06:41:17.958 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.958 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.959 else:
2025-07-02 06:41:17.959 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.959 eqi = None
2025-07-02 06:41:17.959
2025-07-02 06:41:17.959 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.959 # identical
2025-07-02 06:41:17.959
2025-07-02 06:41:17.959 # pump out diffs from before the synch point
2025-07-02 06:41:17.959 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.959
2025-07-02 06:41:17.959 # do intraline marking on the synch pair
2025-07-02 06:41:17.959 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.959 if eqi is None:
2025-07-02 06:41:17.959 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.959 atags = btags = ""
2025-07-02 06:41:17.959 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.959 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.959 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.959 if tag == 'replace':
2025-07-02 06:41:17.960 atags += '^' * la
2025-07-02 06:41:17.960 btags += '^' * lb
2025-07-02 06:41:17.960 elif tag == 'delete':
2025-07-02 06:41:17.960 atags += '-' * la
2025-07-02 06:41:17.960 elif tag == 'insert':
2025-07-02 06:41:17.960 btags += '+' * lb
2025-07-02 06:41:17.960 elif tag == 'equal':
2025-07-02 06:41:17.960 atags += ' ' * la
2025-07-02 06:41:17.960 btags += ' ' * lb
2025-07-02 06:41:17.960 else:
2025-07-02 06:41:17.960 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.960 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.960 else:
2025-07-02 06:41:17.960 # the synch pair is identical
2025-07-02 06:41:17.960 yield ' ' + aelt
2025-07-02 06:41:17.960
2025-07-02 06:41:17.960 # pump out diffs from after the synch point
2025-07-02 06:41:17.960 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.960
2025-07-02 06:41:17.961 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.961 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.961
2025-07-02 06:41:17.961 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.961 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.961 alo = 319, ahi = 1101
2025-07-02 06:41:17.961 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.961 blo = 319, bhi = 1101
2025-07-02 06:41:17.961
2025-07-02 06:41:17.961 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.961 g = []
2025-07-02 06:41:17.961 if alo < ahi:
2025-07-02 06:41:17.961 if blo < bhi:
2025-07-02 06:41:17.961 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.961 else:
2025-07-02 06:41:17.961 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.961 elif blo < bhi:
2025-07-02 06:41:17.961 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.961
2025-07-02 06:41:17.961 > yield from g
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.962 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.962 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.962 alo = 319, ahi = 1101
2025-07-02 06:41:17.962 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.962 blo = 319, bhi = 1101
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.962 r"""
2025-07-02 06:41:17.962 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.962 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.962 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.962 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962 Example:
2025-07-02 06:41:17.962
2025-07-02 06:41:17.963 >>> d = Differ()
2025-07-02 06:41:17.963 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.963 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.963 >>> print(''.join(results), end="")
2025-07-02 06:41:17.963 - abcDefghiJkl
2025-07-02 06:41:17.963 + abcdefGhijkl
2025-07-02 06:41:17.963 """
2025-07-02 06:41:17.963
2025-07-02 06:41:17.963 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.963 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.963 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.963 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.963 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.963
2025-07-02 06:41:17.963 # search for the pair that matches best without being identical
2025-07-02 06:41:17.963 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.964 # on junk -- unless we have to)
2025-07-02 06:41:17.964 for j in range(blo, bhi):
2025-07-02 06:41:17.964 bj = b[j]
2025-07-02 06:41:17.964 cruncher.set_seq2(bj)
2025-07-02 06:41:17.964 for i in range(alo, ahi):
2025-07-02 06:41:17.964 ai = a[i]
2025-07-02 06:41:17.964 if ai == bj:
2025-07-02 06:41:17.964 if eqi is None:
2025-07-02 06:41:17.964 eqi, eqj = i, j
2025-07-02 06:41:17.964 continue
2025-07-02 06:41:17.964 cruncher.set_seq1(ai)
2025-07-02 06:41:17.964 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.964 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.964 # compares by a factor of 3.
2025-07-02 06:41:17.964 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.964 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.964 # of the computation is cached by cruncher
2025-07-02 06:41:17.964 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.964 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.965 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.965 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.965 if best_ratio < cutoff:
2025-07-02 06:41:17.965 # no non-identical "pretty close" pair
2025-07-02 06:41:17.965 if eqi is None:
2025-07-02 06:41:17.965 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.965 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.965 return
2025-07-02 06:41:17.965 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.965 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.965 else:
2025-07-02 06:41:17.965 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.965 eqi = None
2025-07-02 06:41:17.965
2025-07-02 06:41:17.965 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.965 # identical
2025-07-02 06:41:17.965
2025-07-02 06:41:17.965 # pump out diffs from before the synch point
2025-07-02 06:41:17.965 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.966
2025-07-02 06:41:17.966 # do intraline marking on the synch pair
2025-07-02 06:41:17.966 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.966 if eqi is None:
2025-07-02 06:41:17.966 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.966 atags = btags = ""
2025-07-02 06:41:17.966 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.966 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.966 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.966 if tag == 'replace':
2025-07-02 06:41:17.966 atags += '^' * la
2025-07-02 06:41:17.966 btags += '^' * lb
2025-07-02 06:41:17.966 elif tag == 'delete':
2025-07-02 06:41:17.966 atags += '-' * la
2025-07-02 06:41:17.966 elif tag == 'insert':
2025-07-02 06:41:17.966 btags += '+' * lb
2025-07-02 06:41:17.966 elif tag == 'equal':
2025-07-02 06:41:17.966 atags += ' ' * la
2025-07-02 06:41:17.966 btags += ' ' * lb
2025-07-02 06:41:17.967 else:
2025-07-02 06:41:17.967 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.967 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.967 else:
2025-07-02 06:41:17.967 # the synch pair is identical
2025-07-02 06:41:17.967 yield ' ' + aelt
2025-07-02 06:41:17.967
2025-07-02 06:41:17.967 # pump out diffs from after the synch point
2025-07-02 06:41:17.967 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.967
2025-07-02 06:41:17.967 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.967 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.967
2025-07-02 06:41:17.967 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.967 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.967 alo = 320, ahi = 1101
2025-07-02 06:41:17.967 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.967 blo = 320, bhi = 1101
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.968 g = []
2025-07-02 06:41:17.968 if alo < ahi:
2025-07-02 06:41:17.968 if blo < bhi:
2025-07-02 06:41:17.968 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.968 else:
2025-07-02 06:41:17.968 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.968 elif blo < bhi:
2025-07-02 06:41:17.968 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 > yield from g
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.968 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.968 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.968 alo = 320, ahi = 1101
2025-07-02 06:41:17.969 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.969 blo = 320, bhi = 1101
2025-07-02 06:41:17.969
2025-07-02 06:41:17.969 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.969 r"""
2025-07-02 06:41:17.969 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.969 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.969 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.969 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.969
2025-07-02 06:41:17.969 Example:
2025-07-02 06:41:17.969
2025-07-02 06:41:17.969 >>> d = Differ()
2025-07-02 06:41:17.969 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.969 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.969 >>> print(''.join(results), end="")
2025-07-02 06:41:17.969 - abcDefghiJkl
2025-07-02 06:41:17.969 + abcdefGhijkl
2025-07-02 06:41:17.970 """
2025-07-02 06:41:17.970
2025-07-02 06:41:17.970 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.970 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.970 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.970 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.970 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.970
2025-07-02 06:41:17.970 # search for the pair that matches best without being identical
2025-07-02 06:41:17.970 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.970 # on junk -- unless we have to)
2025-07-02 06:41:17.970 for j in range(blo, bhi):
2025-07-02 06:41:17.970 bj = b[j]
2025-07-02 06:41:17.970 cruncher.set_seq2(bj)
2025-07-02 06:41:17.970 for i in range(alo, ahi):
2025-07-02 06:41:17.970 ai = a[i]
2025-07-02 06:41:17.970 if ai == bj:
2025-07-02 06:41:17.970 if eqi is None:
2025-07-02 06:41:17.971 eqi, eqj = i, j
2025-07-02 06:41:17.971 continue
2025-07-02 06:41:17.971 cruncher.set_seq1(ai)
2025-07-02 06:41:17.971 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.971 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.971 # compares by a factor of 3.
2025-07-02 06:41:17.971 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.971 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.971 # of the computation is cached by cruncher
2025-07-02 06:41:17.971 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.971 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.971 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.971 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.971 if best_ratio < cutoff:
2025-07-02 06:41:17.971 # no non-identical "pretty close" pair
2025-07-02 06:41:17.971 if eqi is None:
2025-07-02 06:41:17.971 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.971 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.971 return
2025-07-02 06:41:17.971 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.972 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.972 else:
2025-07-02 06:41:17.972 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.972 eqi = None
2025-07-02 06:41:17.972
2025-07-02 06:41:17.972 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.972 # identical
2025-07-02 06:41:17.972
2025-07-02 06:41:17.972 # pump out diffs from before the synch point
2025-07-02 06:41:17.972 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.972
2025-07-02 06:41:17.972 # do intraline marking on the synch pair
2025-07-02 06:41:17.972 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.972 if eqi is None:
2025-07-02 06:41:17.972 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.972 atags = btags = ""
2025-07-02 06:41:17.972 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.972 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.972 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.973 if tag == 'replace':
2025-07-02 06:41:17.973 atags += '^' * la
2025-07-02 06:41:17.973 btags += '^' * lb
2025-07-02 06:41:17.973 elif tag == 'delete':
2025-07-02 06:41:17.973 atags += '-' * la
2025-07-02 06:41:17.973 elif tag == 'insert':
2025-07-02 06:41:17.973 btags += '+' * lb
2025-07-02 06:41:17.973 elif tag == 'equal':
2025-07-02 06:41:17.973 atags += ' ' * la
2025-07-02 06:41:17.973 btags += ' ' * lb
2025-07-02 06:41:17.973 else:
2025-07-02 06:41:17.973 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.973 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.973 else:
2025-07-02 06:41:17.973 # the synch pair is identical
2025-07-02 06:41:17.973 yield ' ' + aelt
2025-07-02 06:41:17.973
2025-07-02 06:41:17.973 # pump out diffs from after the synch point
2025-07-02 06:41:17.973 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.973
2025-07-02 06:41:17.974 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.974 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.974
2025-07-02 06:41:17.974 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.974 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.974 alo = 321, ahi = 1101
2025-07-02 06:41:17.974 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.974 blo = 321, bhi = 1101
2025-07-02 06:41:17.974
2025-07-02 06:41:17.974 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.974 g = []
2025-07-02 06:41:17.974 if alo < ahi:
2025-07-02 06:41:17.974 if blo < bhi:
2025-07-02 06:41:17.974 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.974 else:
2025-07-02 06:41:17.974 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.974 elif blo < bhi:
2025-07-02 06:41:17.974 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.974
2025-07-02 06:41:17.975 > yield from g
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.975 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.975 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.975 alo = 321, ahi = 1101
2025-07-02 06:41:17.975 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.975 blo = 321, bhi = 1101
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.975 r"""
2025-07-02 06:41:17.975 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.975 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.975 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.975 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975 Example:
2025-07-02 06:41:17.976
2025-07-02 06:41:17.976 >>> d = Differ()
2025-07-02 06:41:17.976 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.976 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.976 >>> print(''.join(results), end="")
2025-07-02 06:41:17.976 - abcDefghiJkl
2025-07-02 06:41:17.976 + abcdefGhijkl
2025-07-02 06:41:17.976 """
2025-07-02 06:41:17.976
2025-07-02 06:41:17.976 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.976 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.976 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.976 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.976 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.976
2025-07-02 06:41:17.976 # search for the pair that matches best without being identical
2025-07-02 06:41:17.976 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.977 # on junk -- unless we have to)
2025-07-02 06:41:17.977 for j in range(blo, bhi):
2025-07-02 06:41:17.977 bj = b[j]
2025-07-02 06:41:17.977 cruncher.set_seq2(bj)
2025-07-02 06:41:17.977 for i in range(alo, ahi):
2025-07-02 06:41:17.977 ai = a[i]
2025-07-02 06:41:17.977 if ai == bj:
2025-07-02 06:41:17.977 if eqi is None:
2025-07-02 06:41:17.977 eqi, eqj = i, j
2025-07-02 06:41:17.977 continue
2025-07-02 06:41:17.977 cruncher.set_seq1(ai)
2025-07-02 06:41:17.977 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.977 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.977 # compares by a factor of 3.
2025-07-02 06:41:17.977 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.977 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.977 # of the computation is cached by cruncher
2025-07-02 06:41:17.977 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.977 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.978 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.978 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.978 if best_ratio < cutoff:
2025-07-02 06:41:17.978 # no non-identical "pretty close" pair
2025-07-02 06:41:17.978 if eqi is None:
2025-07-02 06:41:17.978 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.978 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.978 return
2025-07-02 06:41:17.978 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.978 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.978 else:
2025-07-02 06:41:17.978 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.978 eqi = None
2025-07-02 06:41:17.978
2025-07-02 06:41:17.978 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.978 # identical
2025-07-02 06:41:17.978
2025-07-02 06:41:17.978 # pump out diffs from before the synch point
2025-07-02 06:41:17.978 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.979
2025-07-02 06:41:17.979 # do intraline marking on the synch pair
2025-07-02 06:41:17.979 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.979 if eqi is None:
2025-07-02 06:41:17.979 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.979 atags = btags = ""
2025-07-02 06:41:17.979 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.979 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.979 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.979 if tag == 'replace':
2025-07-02 06:41:17.979 atags += '^' * la
2025-07-02 06:41:17.979 btags += '^' * lb
2025-07-02 06:41:17.979 elif tag == 'delete':
2025-07-02 06:41:17.979 atags += '-' * la
2025-07-02 06:41:17.979 elif tag == 'insert':
2025-07-02 06:41:17.979 btags += '+' * lb
2025-07-02 06:41:17.979 elif tag == 'equal':
2025-07-02 06:41:17.980 atags += ' ' * la
2025-07-02 06:41:17.980 btags += ' ' * lb
2025-07-02 06:41:17.980 else:
2025-07-02 06:41:17.980 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.980 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.980 else:
2025-07-02 06:41:17.980 # the synch pair is identical
2025-07-02 06:41:17.980 yield ' ' + aelt
2025-07-02 06:41:17.980
2025-07-02 06:41:17.980 # pump out diffs from after the synch point
2025-07-02 06:41:17.980 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.980
2025-07-02 06:41:17.980 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.980 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.980
2025-07-02 06:41:17.980 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.980 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.980 alo = 322, ahi = 1101
2025-07-02 06:41:17.981 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.981 blo = 322, bhi = 1101
2025-07-02 06:41:17.981
2025-07-02 06:41:17.981 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.981 g = []
2025-07-02 06:41:17.981 if alo < ahi:
2025-07-02 06:41:17.981 if blo < bhi:
2025-07-02 06:41:17.981 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.981 else:
2025-07-02 06:41:17.981 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.981 elif blo < bhi:
2025-07-02 06:41:17.981 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.981
2025-07-02 06:41:17.981 > yield from g
2025-07-02 06:41:17.981
2025-07-02 06:41:17.981 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.981 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.981
2025-07-02 06:41:17.982 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.982 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.982 alo = 322, ahi = 1101
2025-07-02 06:41:17.982 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.982 blo = 322, bhi = 1101
2025-07-02 06:41:17.982
2025-07-02 06:41:17.982 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.982 r"""
2025-07-02 06:41:17.982 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.982 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.982 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.982 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.982
2025-07-02 06:41:17.982 Example:
2025-07-02 06:41:17.982
2025-07-02 06:41:17.982 >>> d = Differ()
2025-07-02 06:41:17.982 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.982 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.982 >>> print(''.join(results), end="")
2025-07-02 06:41:17.983 - abcDefghiJkl
2025-07-02 06:41:17.983 + abcdefGhijkl
2025-07-02 06:41:17.983 """
2025-07-02 06:41:17.983
2025-07-02 06:41:17.983 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.983 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.983 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.983 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.983 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.983
2025-07-02 06:41:17.983 # search for the pair that matches best without being identical
2025-07-02 06:41:17.983 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.983 # on junk -- unless we have to)
2025-07-02 06:41:17.983 for j in range(blo, bhi):
2025-07-02 06:41:17.983 bj = b[j]
2025-07-02 06:41:17.983 cruncher.set_seq2(bj)
2025-07-02 06:41:17.983 for i in range(alo, ahi):
2025-07-02 06:41:17.984 ai = a[i]
2025-07-02 06:41:17.984 if ai == bj:
2025-07-02 06:41:17.984 if eqi is None:
2025-07-02 06:41:17.984 eqi, eqj = i, j
2025-07-02 06:41:17.984 continue
2025-07-02 06:41:17.984 cruncher.set_seq1(ai)
2025-07-02 06:41:17.984 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.984 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.984 # compares by a factor of 3.
2025-07-02 06:41:17.984 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.984 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.984 # of the computation is cached by cruncher
2025-07-02 06:41:17.984 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.984 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.984 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.984 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.984 if best_ratio < cutoff:
2025-07-02 06:41:17.985 # no non-identical "pretty close" pair
2025-07-02 06:41:17.985 if eqi is None:
2025-07-02 06:41:17.985 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.985 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.985 return
2025-07-02 06:41:17.985 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.985 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.985 else:
2025-07-02 06:41:17.985 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.985 eqi = None
2025-07-02 06:41:17.985
2025-07-02 06:41:17.985 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.985 # identical
2025-07-02 06:41:17.985
2025-07-02 06:41:17.985 # pump out diffs from before the synch point
2025-07-02 06:41:17.985 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.985
2025-07-02 06:41:17.985 # do intraline marking on the synch pair
2025-07-02 06:41:17.985 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.986 if eqi is None:
2025-07-02 06:41:17.986 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.986 atags = btags = ""
2025-07-02 06:41:17.986 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.986 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.986 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.986 if tag == 'replace':
2025-07-02 06:41:17.986 atags += '^' * la
2025-07-02 06:41:17.986 btags += '^' * lb
2025-07-02 06:41:17.986 elif tag == 'delete':
2025-07-02 06:41:17.986 atags += '-' * la
2025-07-02 06:41:17.986 elif tag == 'insert':
2025-07-02 06:41:17.986 btags += '+' * lb
2025-07-02 06:41:17.986 elif tag == 'equal':
2025-07-02 06:41:17.986 atags += ' ' * la
2025-07-02 06:41:17.986 btags += ' ' * lb
2025-07-02 06:41:17.986 else:
2025-07-02 06:41:17.987 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.987 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.987 else:
2025-07-02 06:41:17.987 # the synch pair is identical
2025-07-02 06:41:17.987 yield ' ' + aelt
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987 # pump out diffs from after the synch point
2025-07-02 06:41:17.987 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.987 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.987 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.987 alo = 323, ahi = 1101
2025-07-02 06:41:17.987 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.987 blo = 323, bhi = 1101
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.988 g = []
2025-07-02 06:41:17.988 if alo < ahi:
2025-07-02 06:41:17.988 if blo < bhi:
2025-07-02 06:41:17.988 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.988 else:
2025-07-02 06:41:17.988 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.988 elif blo < bhi:
2025-07-02 06:41:17.988 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.988
2025-07-02 06:41:17.988 > yield from g
2025-07-02 06:41:17.988
2025-07-02 06:41:17.988 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.988 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.988
2025-07-02 06:41:17.988 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.988 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.988 alo = 323, ahi = 1101
2025-07-02 06:41:17.988 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.988 blo = 323, bhi = 1101
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.989 r"""
2025-07-02 06:41:17.989 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.989 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.989 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.989 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989 Example:
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989 >>> d = Differ()
2025-07-02 06:41:17.989 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.989 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.989 >>> print(''.join(results), end="")
2025-07-02 06:41:17.989 - abcDefghiJkl
2025-07-02 06:41:17.989 + abcdefGhijkl
2025-07-02 06:41:17.989 """
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.990 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.990 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.990 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.990 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.990
2025-07-02 06:41:17.990 # search for the pair that matches best without being identical
2025-07-02 06:41:17.990 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.990 # on junk -- unless we have to)
2025-07-02 06:41:17.990 for j in range(blo, bhi):
2025-07-02 06:41:17.990 bj = b[j]
2025-07-02 06:41:17.990 cruncher.set_seq2(bj)
2025-07-02 06:41:17.990 for i in range(alo, ahi):
2025-07-02 06:41:17.990 ai = a[i]
2025-07-02 06:41:17.990 if ai == bj:
2025-07-02 06:41:17.990 if eqi is None:
2025-07-02 06:41:17.990 eqi, eqj = i, j
2025-07-02 06:41:17.990 continue
2025-07-02 06:41:17.990 cruncher.set_seq1(ai)
2025-07-02 06:41:17.990 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.990 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.991 # compares by a factor of 3.
2025-07-02 06:41:17.991 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.991 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.991 # of the computation is cached by cruncher
2025-07-02 06:41:17.991 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.991 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.991 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.991 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.991 if best_ratio < cutoff:
2025-07-02 06:41:17.991 # no non-identical "pretty close" pair
2025-07-02 06:41:17.991 if eqi is None:
2025-07-02 06:41:17.991 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.991 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.991 return
2025-07-02 06:41:17.991 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.991 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.991 else:
2025-07-02 06:41:17.991 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.991 eqi = None
2025-07-02 06:41:17.991
2025-07-02 06:41:17.992 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.992 # identical
2025-07-02 06:41:17.992
2025-07-02 06:41:17.992 # pump out diffs from before the synch point
2025-07-02 06:41:17.992 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.992
2025-07-02 06:41:17.992 # do intraline marking on the synch pair
2025-07-02 06:41:17.992 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.992 if eqi is None:
2025-07-02 06:41:17.992 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.992 atags = btags = ""
2025-07-02 06:41:17.992 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.992 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.992 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.992 if tag == 'replace':
2025-07-02 06:41:17.992 atags += '^' * la
2025-07-02 06:41:17.992 btags += '^' * lb
2025-07-02 06:41:17.992 elif tag == 'delete':
2025-07-02 06:41:17.992 atags += '-' * la
2025-07-02 06:41:17.992 elif tag == 'insert':
2025-07-02 06:41:17.993 btags += '+' * lb
2025-07-02 06:41:17.993 elif tag == 'equal':
2025-07-02 06:41:17.993 atags += ' ' * la
2025-07-02 06:41:17.993 btags += ' ' * lb
2025-07-02 06:41:17.993 else:
2025-07-02 06:41:17.993 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.993 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.993 else:
2025-07-02 06:41:17.993 # the synch pair is identical
2025-07-02 06:41:17.993 yield ' ' + aelt
2025-07-02 06:41:17.993
2025-07-02 06:41:17.993 # pump out diffs from after the synch point
2025-07-02 06:41:17.993 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.993
2025-07-02 06:41:17.993 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.993 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.993
2025-07-02 06:41:17.993 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.993 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.993 alo = 324, ahi = 1101
2025-07-02 06:41:17.993 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.994 blo = 324, bhi = 1101
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.994 g = []
2025-07-02 06:41:17.994 if alo < ahi:
2025-07-02 06:41:17.994 if blo < bhi:
2025-07-02 06:41:17.994 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.994 else:
2025-07-02 06:41:17.994 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.994 elif blo < bhi:
2025-07-02 06:41:17.994 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 > yield from g
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.994 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.994 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:17.995 alo = 324, ahi = 1101
2025-07-02 06:41:17.995 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:17.995 blo = 324, bhi = 1101
2025-07-02 06:41:17.995
2025-07-02 06:41:17.995 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.995 r"""
2025-07-02 06:41:17.995 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.995 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.995 synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.995 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.995
2025-07-02 06:41:17.995 Example:
2025-07-02 06:41:17.995
2025-07-02 06:41:17.995 >>> d = Differ()
2025-07-02 06:41:17.995 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.995 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.995 >>> print(''.join(results), end="")
2025-07-02 06:41:17.996 - abcDefghiJkl
2025-07-02 06:41:17.996 + abcdefGhijkl
2025-07-02 06:41:17.996 """
2025-07-02 06:41:17.996
2025-07-02 06:41:17.996 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.996 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.996 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.996 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.996 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:17.996
2025-07-02 06:41:17.996 # search for the pair that matches best without being identical
2025-07-02 06:41:17.996 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.996 # on junk -- unless we have to)
2025-07-02 06:41:17.996 for j in range(blo, bhi):
2025-07-02 06:41:17.996 bj = b[j]
2025-07-02 06:41:17.996 cruncher.set_seq2(bj)
2025-07-02 06:41:17.996 for i in range(alo, ahi):
2025-07-02 06:41:17.997 ai = a[i]
2025-07-02 06:41:17.997 if ai == bj:
2025-07-02 06:41:17.997 if eqi is None:
2025-07-02 06:41:17.997 eqi, eqj = i, j
2025-07-02 06:41:17.997 continue
2025-07-02 06:41:17.997 cruncher.set_seq1(ai)
2025-07-02 06:41:17.997 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.997 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.997 # compares by a factor of 3.
2025-07-02 06:41:17.997 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.997 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.997 # of the computation is cached by cruncher
2025-07-02 06:41:17.997 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.997 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.997 cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.997 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.997 if best_ratio < cutoff:
2025-07-02 06:41:17.997 # no non-identical "pretty close" pair
2025-07-02 06:41:17.997 if eqi is None:
2025-07-02 06:41:17.997 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.998 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.998 return
2025-07-02 06:41:17.998 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.998 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.998 else:
2025-07-02 06:41:17.998 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.998 eqi = None
2025-07-02 06:41:17.998
2025-07-02 06:41:17.998 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.998 # identical
2025-07-02 06:41:17.998
2025-07-02 06:41:17.998 # pump out diffs from before the synch point
2025-07-02 06:41:17.998 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.998
2025-07-02 06:41:17.998 # do intraline marking on the synch pair
2025-07-02 06:41:17.998 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.998 if eqi is None:
2025-07-02 06:41:17.998 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.998 atags = btags = ""
2025-07-02 06:41:17.998 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.999 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.999 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.999 if tag == 'replace':
2025-07-02 06:41:17.999 atags += '^' * la
2025-07-02 06:41:17.999 btags += '^' * lb
2025-07-02 06:41:17.999 elif tag == 'delete':
2025-07-02 06:41:17.999 atags += '-' * la
2025-07-02 06:41:17.999 elif tag == 'insert':
2025-07-02 06:41:17.999 btags += '+' * lb
2025-07-02 06:41:17.999 elif tag == 'equal':
2025-07-02 06:41:17.999 atags += ' ' * la
2025-07-02 06:41:17.999 btags += ' ' * lb
2025-07-02 06:41:17.999 else:
2025-07-02 06:41:17.999 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.999 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.999 else:
2025-07-02 06:41:17.999 # the synch pair is identical
2025-07-02 06:41:17.999 yield ' ' + aelt
2025-07-02 06:41:17.999
2025-07-02 06:41:17.999 # pump out diffs from after the synch point
2025-07-02 06:41:17.999 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.000
2025-07-02 06:41:18.000 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.000 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.000
2025-07-02 06:41:18.000 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.000 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.000 alo = 325, ahi = 1101
2025-07-02 06:41:18.000 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.000 blo = 325, bhi = 1101
2025-07-02 06:41:18.000
2025-07-02 06:41:18.000 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.000 g = []
2025-07-02 06:41:18.000 if alo < ahi:
2025-07-02 06:41:18.000 if blo < bhi:
2025-07-02 06:41:18.000 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.000 else:
2025-07-02 06:41:18.000 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.000 elif blo < bhi:
2025-07-02 06:41:18.000 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 > yield from g
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.001 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.001 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.001 alo = 325, ahi = 1101
2025-07-02 06:41:18.001 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.001 blo = 325, bhi = 1101
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.001 r"""
2025-07-02 06:41:18.001 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.001 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.001 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.001 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 Example:
2025-07-02 06:41:18.002
2025-07-02 06:41:18.002 >>> d = Differ()
2025-07-02 06:41:18.002 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.002 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.002 >>> print(''.join(results), end="")
2025-07-02 06:41:18.002 - abcDefghiJkl
2025-07-02 06:41:18.002 + abcdefGhijkl
2025-07-02 06:41:18.002 """
2025-07-02 06:41:18.002
2025-07-02 06:41:18.002 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.002 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.002 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.002 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.002 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.002
2025-07-02 06:41:18.002 # search for the pair that matches best without being identical
2025-07-02 06:41:18.002 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.002 # on junk -- unless we have to)
2025-07-02 06:41:18.003 for j in range(blo, bhi):
2025-07-02 06:41:18.003 bj = b[j]
2025-07-02 06:41:18.003 cruncher.set_seq2(bj)
2025-07-02 06:41:18.003 for i in range(alo, ahi):
2025-07-02 06:41:18.003 ai = a[i]
2025-07-02 06:41:18.003 if ai == bj:
2025-07-02 06:41:18.003 if eqi is None:
2025-07-02 06:41:18.003 eqi, eqj = i, j
2025-07-02 06:41:18.003 continue
2025-07-02 06:41:18.003 cruncher.set_seq1(ai)
2025-07-02 06:41:18.003 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.003 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.003 # compares by a factor of 3.
2025-07-02 06:41:18.003 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.003 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.003 # of the computation is cached by cruncher
2025-07-02 06:41:18.003 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.003 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.003 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.003 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.004 if best_ratio < cutoff:
2025-07-02 06:41:18.004 # no non-identical "pretty close" pair
2025-07-02 06:41:18.004 if eqi is None:
2025-07-02 06:41:18.004 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.004 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.004 return
2025-07-02 06:41:18.004 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.004 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.004 else:
2025-07-02 06:41:18.004 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.004 eqi = None
2025-07-02 06:41:18.004
2025-07-02 06:41:18.004 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.004 # identical
2025-07-02 06:41:18.004
2025-07-02 06:41:18.004 # pump out diffs from before the synch point
2025-07-02 06:41:18.004 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.004
2025-07-02 06:41:18.004 # do intraline marking on the synch pair
2025-07-02 06:41:18.005 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.005 if eqi is None:
2025-07-02 06:41:18.005 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.005 atags = btags = ""
2025-07-02 06:41:18.005 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.005 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.005 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.005 if tag == 'replace':
2025-07-02 06:41:18.005 atags += '^' * la
2025-07-02 06:41:18.005 btags += '^' * lb
2025-07-02 06:41:18.005 elif tag == 'delete':
2025-07-02 06:41:18.005 atags += '-' * la
2025-07-02 06:41:18.005 elif tag == 'insert':
2025-07-02 06:41:18.005 btags += '+' * lb
2025-07-02 06:41:18.005 elif tag == 'equal':
2025-07-02 06:41:18.005 atags += ' ' * la
2025-07-02 06:41:18.005 btags += ' ' * lb
2025-07-02 06:41:18.005 else:
2025-07-02 06:41:18.005 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.005 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.006 else:
2025-07-02 06:41:18.006 # the synch pair is identical
2025-07-02 06:41:18.006 yield ' ' + aelt
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006 # pump out diffs from after the synch point
2025-07-02 06:41:18.006 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.006 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.006 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.006 alo = 326, ahi = 1101
2025-07-02 06:41:18.006 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.006 blo = 326, bhi = 1101
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.006 g = []
2025-07-02 06:41:18.006 if alo < ahi:
2025-07-02 06:41:18.006 if blo < bhi:
2025-07-02 06:41:18.007 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.007 else:
2025-07-02 06:41:18.007 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.007 elif blo < bhi:
2025-07-02 06:41:18.007 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 > yield from g
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.007 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.007 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.007 alo = 326, ahi = 1101
2025-07-02 06:41:18.007 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.007 blo = 326, bhi = 1101
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.007 r"""
2025-07-02 06:41:18.007 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.008 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.008 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.008 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.008
2025-07-02 06:41:18.008 Example:
2025-07-02 06:41:18.008
2025-07-02 06:41:18.008 >>> d = Differ()
2025-07-02 06:41:18.008 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.008 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.008 >>> print(''.join(results), end="")
2025-07-02 06:41:18.008 - abcDefghiJkl
2025-07-02 06:41:18.008 + abcdefGhijkl
2025-07-02 06:41:18.008 """
2025-07-02 06:41:18.008
2025-07-02 06:41:18.008 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.008 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.008 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.008 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.009 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.009
2025-07-02 06:41:18.009 # search for the pair that matches best without being identical
2025-07-02 06:41:18.009 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.009 # on junk -- unless we have to)
2025-07-02 06:41:18.009 for j in range(blo, bhi):
2025-07-02 06:41:18.009 bj = b[j]
2025-07-02 06:41:18.009 cruncher.set_seq2(bj)
2025-07-02 06:41:18.009 for i in range(alo, ahi):
2025-07-02 06:41:18.009 ai = a[i]
2025-07-02 06:41:18.009 if ai == bj:
2025-07-02 06:41:18.009 if eqi is None:
2025-07-02 06:41:18.009 eqi, eqj = i, j
2025-07-02 06:41:18.009 continue
2025-07-02 06:41:18.009 cruncher.set_seq1(ai)
2025-07-02 06:41:18.009 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.009 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.009 # compares by a factor of 3.
2025-07-02 06:41:18.009 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.009 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.010 # of the computation is cached by cruncher
2025-07-02 06:41:18.010 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.010 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.010 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.010 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.010 if best_ratio < cutoff:
2025-07-02 06:41:18.010 # no non-identical "pretty close" pair
2025-07-02 06:41:18.010 if eqi is None:
2025-07-02 06:41:18.010 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.010 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.010 return
2025-07-02 06:41:18.010 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.010 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.010 else:
2025-07-02 06:41:18.010 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.010 eqi = None
2025-07-02 06:41:18.010
2025-07-02 06:41:18.010 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.010 # identical
2025-07-02 06:41:18.010
2025-07-02 06:41:18.011 # pump out diffs from before the synch point
2025-07-02 06:41:18.011 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.011
2025-07-02 06:41:18.011 # do intraline marking on the synch pair
2025-07-02 06:41:18.011 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.011 if eqi is None:
2025-07-02 06:41:18.011 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.011 atags = btags = ""
2025-07-02 06:41:18.011 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.011 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.011 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.011 if tag == 'replace':
2025-07-02 06:41:18.011 atags += '^' * la
2025-07-02 06:41:18.011 btags += '^' * lb
2025-07-02 06:41:18.011 elif tag == 'delete':
2025-07-02 06:41:18.011 atags += '-' * la
2025-07-02 06:41:18.011 elif tag == 'insert':
2025-07-02 06:41:18.011 btags += '+' * lb
2025-07-02 06:41:18.012 elif tag == 'equal':
2025-07-02 06:41:18.012 atags += ' ' * la
2025-07-02 06:41:18.012 btags += ' ' * lb
2025-07-02 06:41:18.012 else:
2025-07-02 06:41:18.012 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.012 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.012 else:
2025-07-02 06:41:18.012 # the synch pair is identical
2025-07-02 06:41:18.012 yield ' ' + aelt
2025-07-02 06:41:18.012
2025-07-02 06:41:18.012 # pump out diffs from after the synch point
2025-07-02 06:41:18.012 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.012
2025-07-02 06:41:18.012 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.012 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.012
2025-07-02 06:41:18.012 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.013 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.013 alo = 327, ahi = 1101
2025-07-02 06:41:18.013 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.013 blo = 327, bhi = 1101
2025-07-02 06:41:18.013
2025-07-02 06:41:18.013 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.013 g = []
2025-07-02 06:41:18.013 if alo < ahi:
2025-07-02 06:41:18.013 if blo < bhi:
2025-07-02 06:41:18.013 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.013 else:
2025-07-02 06:41:18.013 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.013 elif blo < bhi:
2025-07-02 06:41:18.013 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.013
2025-07-02 06:41:18.013 > yield from g
2025-07-02 06:41:18.013
2025-07-02 06:41:18.013 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.013 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.014 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.014 alo = 327, ahi = 1101
2025-07-02 06:41:18.014 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.014 blo = 327, bhi = 1101
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.014 r"""
2025-07-02 06:41:18.014 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.014 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.014 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.014 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014 Example:
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014 >>> d = Differ()
2025-07-02 06:41:18.014 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.015 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.015 >>> print(''.join(results), end="")
2025-07-02 06:41:18.015 - abcDefghiJkl
2025-07-02 06:41:18.015 + abcdefGhijkl
2025-07-02 06:41:18.015 """
2025-07-02 06:41:18.015
2025-07-02 06:41:18.015 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.015 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.015 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.015 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.015 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.015
2025-07-02 06:41:18.015 # search for the pair that matches best without being identical
2025-07-02 06:41:18.015 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.015 # on junk -- unless we have to)
2025-07-02 06:41:18.015 for j in range(blo, bhi):
2025-07-02 06:41:18.015 bj = b[j]
2025-07-02 06:41:18.016 cruncher.set_seq2(bj)
2025-07-02 06:41:18.016 for i in range(alo, ahi):
2025-07-02 06:41:18.016 ai = a[i]
2025-07-02 06:41:18.016 if ai == bj:
2025-07-02 06:41:18.016 if eqi is None:
2025-07-02 06:41:18.016 eqi, eqj = i, j
2025-07-02 06:41:18.016 continue
2025-07-02 06:41:18.016 cruncher.set_seq1(ai)
2025-07-02 06:41:18.016 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.016 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.016 # compares by a factor of 3.
2025-07-02 06:41:18.016 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.016 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.016 # of the computation is cached by cruncher
2025-07-02 06:41:18.016 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.016 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.016 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.016 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.016 if best_ratio < cutoff:
2025-07-02 06:41:18.017 # no non-identical "pretty close" pair
2025-07-02 06:41:18.017 if eqi is None:
2025-07-02 06:41:18.017 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.017 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.017 return
2025-07-02 06:41:18.017 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.017 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.017 else:
2025-07-02 06:41:18.017 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.017 eqi = None
2025-07-02 06:41:18.017
2025-07-02 06:41:18.017 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.017 # identical
2025-07-02 06:41:18.017
2025-07-02 06:41:18.017 # pump out diffs from before the synch point
2025-07-02 06:41:18.017 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.017
2025-07-02 06:41:18.017 # do intraline marking on the synch pair
2025-07-02 06:41:18.017 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.018 if eqi is None:
2025-07-02 06:41:18.018 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.018 atags = btags = ""
2025-07-02 06:41:18.018 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.018 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.018 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.018 if tag == 'replace':
2025-07-02 06:41:18.018 atags += '^' * la
2025-07-02 06:41:18.018 btags += '^' * lb
2025-07-02 06:41:18.018 elif tag == 'delete':
2025-07-02 06:41:18.018 atags += '-' * la
2025-07-02 06:41:18.018 elif tag == 'insert':
2025-07-02 06:41:18.018 btags += '+' * lb
2025-07-02 06:41:18.018 elif tag == 'equal':
2025-07-02 06:41:18.018 atags += ' ' * la
2025-07-02 06:41:18.018 btags += ' ' * lb
2025-07-02 06:41:18.018 else:
2025-07-02 06:41:18.018 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.018 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.018 else:
2025-07-02 06:41:18.019 # the synch pair is identical
2025-07-02 06:41:18.019 yield ' ' + aelt
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019 # pump out diffs from after the synch point
2025-07-02 06:41:18.019 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.019 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.019 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.019 alo = 328, ahi = 1101
2025-07-02 06:41:18.019 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.019 blo = 328, bhi = 1101
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.019 g = []
2025-07-02 06:41:18.019 if alo < ahi:
2025-07-02 06:41:18.019 if blo < bhi:
2025-07-02 06:41:18.019 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.020 else:
2025-07-02 06:41:18.020 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.020 elif blo < bhi:
2025-07-02 06:41:18.020 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 > yield from g
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.020 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.020 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.020 alo = 328, ahi = 1101
2025-07-02 06:41:18.020 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.020 blo = 328, bhi = 1101
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.020 r"""
2025-07-02 06:41:18.020 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.021 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.021 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.021 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.021
2025-07-02 06:41:18.021 Example:
2025-07-02 06:41:18.021
2025-07-02 06:41:18.021 >>> d = Differ()
2025-07-02 06:41:18.021 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.021 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.021 >>> print(''.join(results), end="")
2025-07-02 06:41:18.021 - abcDefghiJkl
2025-07-02 06:41:18.021 + abcdefGhijkl
2025-07-02 06:41:18.021 """
2025-07-02 06:41:18.021
2025-07-02 06:41:18.021 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.021 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.022 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.022 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.022 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.022
2025-07-02 06:41:18.022 # search for the pair that matches best without being identical
2025-07-02 06:41:18.022 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.022 # on junk -- unless we have to)
2025-07-02 06:41:18.022 for j in range(blo, bhi):
2025-07-02 06:41:18.022 bj = b[j]
2025-07-02 06:41:18.022 cruncher.set_seq2(bj)
2025-07-02 06:41:18.022 for i in range(alo, ahi):
2025-07-02 06:41:18.022 ai = a[i]
2025-07-02 06:41:18.022 if ai == bj:
2025-07-02 06:41:18.022 if eqi is None:
2025-07-02 06:41:18.022 eqi, eqj = i, j
2025-07-02 06:41:18.022 continue
2025-07-02 06:41:18.022 cruncher.set_seq1(ai)
2025-07-02 06:41:18.022 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.022 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.023 # compares by a factor of 3.
2025-07-02 06:41:18.023 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.023 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.023 # of the computation is cached by cruncher
2025-07-02 06:41:18.023 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.023 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.023 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.023 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.023 if best_ratio < cutoff:
2025-07-02 06:41:18.023 # no non-identical "pretty close" pair
2025-07-02 06:41:18.023 if eqi is None:
2025-07-02 06:41:18.023 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.023 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.023 return
2025-07-02 06:41:18.023 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.023 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.023 else:
2025-07-02 06:41:18.023 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.023 eqi = None
2025-07-02 06:41:18.024
2025-07-02 06:41:18.024 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.024 # identical
2025-07-02 06:41:18.024
2025-07-02 06:41:18.024 # pump out diffs from before the synch point
2025-07-02 06:41:18.024 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.024
2025-07-02 06:41:18.024 # do intraline marking on the synch pair
2025-07-02 06:41:18.024 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.024 if eqi is None:
2025-07-02 06:41:18.024 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.024 atags = btags = ""
2025-07-02 06:41:18.024 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.024 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.024 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.024 if tag == 'replace':
2025-07-02 06:41:18.024 atags += '^' * la
2025-07-02 06:41:18.024 btags += '^' * lb
2025-07-02 06:41:18.024 elif tag == 'delete':
2025-07-02 06:41:18.024 atags += '-' * la
2025-07-02 06:41:18.025 elif tag == 'insert':
2025-07-02 06:41:18.025 btags += '+' * lb
2025-07-02 06:41:18.025 elif tag == 'equal':
2025-07-02 06:41:18.025 atags += ' ' * la
2025-07-02 06:41:18.025 btags += ' ' * lb
2025-07-02 06:41:18.025 else:
2025-07-02 06:41:18.025 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.025 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.025 else:
2025-07-02 06:41:18.025 # the synch pair is identical
2025-07-02 06:41:18.025 yield ' ' + aelt
2025-07-02 06:41:18.025
2025-07-02 06:41:18.025 # pump out diffs from after the synch point
2025-07-02 06:41:18.025 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.025
2025-07-02 06:41:18.025 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.025 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.025
2025-07-02 06:41:18.025 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.025 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.026 alo = 329, ahi = 1101
2025-07-02 06:41:18.026 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.026 blo = 329, bhi = 1101
2025-07-02 06:41:18.026
2025-07-02 06:41:18.026 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.026 g = []
2025-07-02 06:41:18.026 if alo < ahi:
2025-07-02 06:41:18.026 if blo < bhi:
2025-07-02 06:41:18.026 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.026 else:
2025-07-02 06:41:18.026 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.026 elif blo < bhi:
2025-07-02 06:41:18.026 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.026
2025-07-02 06:41:18.026 > yield from g
2025-07-02 06:41:18.026
2025-07-02 06:41:18.026 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.026 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.027 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.027 alo = 329, ahi = 1101
2025-07-02 06:41:18.027 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.027 blo = 329, bhi = 1101
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.027 r"""
2025-07-02 06:41:18.027 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.027 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.027 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.027 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027 Example:
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027 >>> d = Differ()
2025-07-02 06:41:18.027 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.027 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.027 >>> print(''.join(results), end="")
2025-07-02 06:41:18.028 - abcDefghiJkl
2025-07-02 06:41:18.028 + abcdefGhijkl
2025-07-02 06:41:18.028 """
2025-07-02 06:41:18.028
2025-07-02 06:41:18.028 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.028 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.028 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.028 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.028 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.028
2025-07-02 06:41:18.028 # search for the pair that matches best without being identical
2025-07-02 06:41:18.028 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.028 # on junk -- unless we have to)
2025-07-02 06:41:18.028 for j in range(blo, bhi):
2025-07-02 06:41:18.028 bj = b[j]
2025-07-02 06:41:18.028 cruncher.set_seq2(bj)
2025-07-02 06:41:18.028 for i in range(alo, ahi):
2025-07-02 06:41:18.028 ai = a[i]
2025-07-02 06:41:18.029 if ai == bj:
2025-07-02 06:41:18.029 if eqi is None:
2025-07-02 06:41:18.029 eqi, eqj = i, j
2025-07-02 06:41:18.029 continue
2025-07-02 06:41:18.029 cruncher.set_seq1(ai)
2025-07-02 06:41:18.029 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.029 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.029 # compares by a factor of 3.
2025-07-02 06:41:18.029 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.029 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.029 # of the computation is cached by cruncher
2025-07-02 06:41:18.029 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.029 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.029 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.029 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.029 if best_ratio < cutoff:
2025-07-02 06:41:18.029 # no non-identical "pretty close" pair
2025-07-02 06:41:18.029 if eqi is None:
2025-07-02 06:41:18.029 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.030 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.030 return
2025-07-02 06:41:18.030 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.030 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.030 else:
2025-07-02 06:41:18.030 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.030 eqi = None
2025-07-02 06:41:18.030
2025-07-02 06:41:18.030 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.030 # identical
2025-07-02 06:41:18.030
2025-07-02 06:41:18.030 # pump out diffs from before the synch point
2025-07-02 06:41:18.030 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.030
2025-07-02 06:41:18.030 # do intraline marking on the synch pair
2025-07-02 06:41:18.030 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.030 if eqi is None:
2025-07-02 06:41:18.030 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.030 atags = btags = ""
2025-07-02 06:41:18.031 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.031 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.031 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.031 if tag == 'replace':
2025-07-02 06:41:18.031 atags += '^' * la
2025-07-02 06:41:18.031 btags += '^' * lb
2025-07-02 06:41:18.031 elif tag == 'delete':
2025-07-02 06:41:18.031 atags += '-' * la
2025-07-02 06:41:18.031 elif tag == 'insert':
2025-07-02 06:41:18.031 btags += '+' * lb
2025-07-02 06:41:18.031 elif tag == 'equal':
2025-07-02 06:41:18.031 atags += ' ' * la
2025-07-02 06:41:18.031 btags += ' ' * lb
2025-07-02 06:41:18.031 else:
2025-07-02 06:41:18.031 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.031 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.031 else:
2025-07-02 06:41:18.031 # the synch pair is identical
2025-07-02 06:41:18.031 yield ' ' + aelt
2025-07-02 06:41:18.031
2025-07-02 06:41:18.032 # pump out diffs from after the synch point
2025-07-02 06:41:18.032 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.032
2025-07-02 06:41:18.032 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.032 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.032
2025-07-02 06:41:18.032 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.032 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.032 alo = 330, ahi = 1101
2025-07-02 06:41:18.032 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.032 blo = 330, bhi = 1101
2025-07-02 06:41:18.032
2025-07-02 06:41:18.032 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.032 g = []
2025-07-02 06:41:18.032 if alo < ahi:
2025-07-02 06:41:18.032 if blo < bhi:
2025-07-02 06:41:18.032 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.032 else:
2025-07-02 06:41:18.032 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.032 elif blo < bhi:
2025-07-02 06:41:18.033 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 > yield from g
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.033 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.033 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.033 alo = 330, ahi = 1101
2025-07-02 06:41:18.033 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.033 blo = 330, bhi = 1101
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.033 r"""
2025-07-02 06:41:18.033 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.033 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.033 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.033 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.033
2025-07-02 06:41:18.034 Example:
2025-07-02 06:41:18.034
2025-07-02 06:41:18.034 >>> d = Differ()
2025-07-02 06:41:18.034 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.034 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.034 >>> print(''.join(results), end="")
2025-07-02 06:41:18.034 - abcDefghiJkl
2025-07-02 06:41:18.034 + abcdefGhijkl
2025-07-02 06:41:18.034 """
2025-07-02 06:41:18.034
2025-07-02 06:41:18.034 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.034 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.034 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.034 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.034 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.034
2025-07-02 06:41:18.034 # search for the pair that matches best without being identical
2025-07-02 06:41:18.034 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.034 # on junk -- unless we have to)
2025-07-02 06:41:18.035 for j in range(blo, bhi):
2025-07-02 06:41:18.035 bj = b[j]
2025-07-02 06:41:18.035 cruncher.set_seq2(bj)
2025-07-02 06:41:18.035 for i in range(alo, ahi):
2025-07-02 06:41:18.035 ai = a[i]
2025-07-02 06:41:18.035 if ai == bj:
2025-07-02 06:41:18.035 if eqi is None:
2025-07-02 06:41:18.035 eqi, eqj = i, j
2025-07-02 06:41:18.035 continue
2025-07-02 06:41:18.035 cruncher.set_seq1(ai)
2025-07-02 06:41:18.035 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.035 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.035 # compares by a factor of 3.
2025-07-02 06:41:18.035 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.035 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.035 # of the computation is cached by cruncher
2025-07-02 06:41:18.035 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.036 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.036 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.036 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.036 if best_ratio < cutoff:
2025-07-02 06:41:18.036 # no non-identical "pretty close" pair
2025-07-02 06:41:18.036 if eqi is None:
2025-07-02 06:41:18.036 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.036 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.036 return
2025-07-02 06:41:18.036 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.036 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.036 else:
2025-07-02 06:41:18.036 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.036 eqi = None
2025-07-02 06:41:18.036
2025-07-02 06:41:18.036 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.036 # identical
2025-07-02 06:41:18.036
2025-07-02 06:41:18.036 # pump out diffs from before the synch point
2025-07-02 06:41:18.036 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.037
2025-07-02 06:41:18.037 # do intraline marking on the synch pair
2025-07-02 06:41:18.037 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.037 if eqi is None:
2025-07-02 06:41:18.037 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.037 atags = btags = ""
2025-07-02 06:41:18.037 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.037 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.037 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.037 if tag == 'replace':
2025-07-02 06:41:18.037 atags += '^' * la
2025-07-02 06:41:18.037 btags += '^' * lb
2025-07-02 06:41:18.037 elif tag == 'delete':
2025-07-02 06:41:18.037 atags += '-' * la
2025-07-02 06:41:18.037 elif tag == 'insert':
2025-07-02 06:41:18.037 btags += '+' * lb
2025-07-02 06:41:18.037 elif tag == 'equal':
2025-07-02 06:41:18.037 atags += ' ' * la
2025-07-02 06:41:18.037 btags += ' ' * lb
2025-07-02 06:41:18.037 else:
2025-07-02 06:41:18.038 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.038 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.038 else:
2025-07-02 06:41:18.038 # the synch pair is identical
2025-07-02 06:41:18.038 yield ' ' + aelt
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038 # pump out diffs from after the synch point
2025-07-02 06:41:18.038 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.038 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.038 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.038 alo = 331, ahi = 1101
2025-07-02 06:41:18.038 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.038 blo = 331, bhi = 1101
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.038 g = []
2025-07-02 06:41:18.039 if alo < ahi:
2025-07-02 06:41:18.039 if blo < bhi:
2025-07-02 06:41:18.039 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.039 else:
2025-07-02 06:41:18.039 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.039 elif blo < bhi:
2025-07-02 06:41:18.039 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.039
2025-07-02 06:41:18.039 > yield from g
2025-07-02 06:41:18.039
2025-07-02 06:41:18.039 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.039 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.039
2025-07-02 06:41:18.039 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.039 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.039 alo = 331, ahi = 1101
2025-07-02 06:41:18.039 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.039 blo = 331, bhi = 1101
2025-07-02 06:41:18.039
2025-07-02 06:41:18.040 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.040 r"""
2025-07-02 06:41:18.040 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.040 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.040 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.040 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.040
2025-07-02 06:41:18.040 Example:
2025-07-02 06:41:18.040
2025-07-02 06:41:18.040 >>> d = Differ()
2025-07-02 06:41:18.040 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.040 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.040 >>> print(''.join(results), end="")
2025-07-02 06:41:18.040 - abcDefghiJkl
2025-07-02 06:41:18.040 + abcdefGhijkl
2025-07-02 06:41:18.040 """
2025-07-02 06:41:18.040
2025-07-02 06:41:18.040 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.041 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.041 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.041 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.041 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.041
2025-07-02 06:41:18.041 # search for the pair that matches best without being identical
2025-07-02 06:41:18.041 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.041 # on junk -- unless we have to)
2025-07-02 06:41:18.041 for j in range(blo, bhi):
2025-07-02 06:41:18.041 bj = b[j]
2025-07-02 06:41:18.041 cruncher.set_seq2(bj)
2025-07-02 06:41:18.041 for i in range(alo, ahi):
2025-07-02 06:41:18.041 ai = a[i]
2025-07-02 06:41:18.041 if ai == bj:
2025-07-02 06:41:18.041 if eqi is None:
2025-07-02 06:41:18.041 eqi, eqj = i, j
2025-07-02 06:41:18.041 continue
2025-07-02 06:41:18.041 cruncher.set_seq1(ai)
2025-07-02 06:41:18.042 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.042 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.042 # compares by a factor of 3.
2025-07-02 06:41:18.042 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.042 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.042 # of the computation is cached by cruncher
2025-07-02 06:41:18.042 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.042 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.042 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.042 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.042 if best_ratio < cutoff:
2025-07-02 06:41:18.042 # no non-identical "pretty close" pair
2025-07-02 06:41:18.042 if eqi is None:
2025-07-02 06:41:18.042 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.042 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.042 return
2025-07-02 06:41:18.042 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.042 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.042 else:
2025-07-02 06:41:18.042 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.043 eqi = None
2025-07-02 06:41:18.043
2025-07-02 06:41:18.043 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.043 # identical
2025-07-02 06:41:18.043
2025-07-02 06:41:18.043 # pump out diffs from before the synch point
2025-07-02 06:41:18.043 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.043
2025-07-02 06:41:18.043 # do intraline marking on the synch pair
2025-07-02 06:41:18.043 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.043 if eqi is None:
2025-07-02 06:41:18.043 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.043 atags = btags = ""
2025-07-02 06:41:18.043 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.043 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.043 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.043 if tag == 'replace':
2025-07-02 06:41:18.043 atags += '^' * la
2025-07-02 06:41:18.043 btags += '^' * lb
2025-07-02 06:41:18.044 elif tag == 'delete':
2025-07-02 06:41:18.044 atags += '-' * la
2025-07-02 06:41:18.044 elif tag == 'insert':
2025-07-02 06:41:18.044 btags += '+' * lb
2025-07-02 06:41:18.044 elif tag == 'equal':
2025-07-02 06:41:18.044 atags += ' ' * la
2025-07-02 06:41:18.044 btags += ' ' * lb
2025-07-02 06:41:18.044 else:
2025-07-02 06:41:18.044 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.044 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.044 else:
2025-07-02 06:41:18.044 # the synch pair is identical
2025-07-02 06:41:18.044 yield ' ' + aelt
2025-07-02 06:41:18.044
2025-07-02 06:41:18.044 # pump out diffs from after the synch point
2025-07-02 06:41:18.044 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.044
2025-07-02 06:41:18.044 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.044 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.044
2025-07-02 06:41:18.045 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.045 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.045 alo = 334, ahi = 1101
2025-07-02 06:41:18.045 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.045 blo = 334, bhi = 1101
2025-07-02 06:41:18.045
2025-07-02 06:41:18.045 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.045 g = []
2025-07-02 06:41:18.045 if alo < ahi:
2025-07-02 06:41:18.045 if blo < bhi:
2025-07-02 06:41:18.045 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.045 else:
2025-07-02 06:41:18.045 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.045 elif blo < bhi:
2025-07-02 06:41:18.045 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.045
2025-07-02 06:41:18.045 > yield from g
2025-07-02 06:41:18.045
2025-07-02 06:41:18.045 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.045 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.046 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.046 alo = 334, ahi = 1101
2025-07-02 06:41:18.046 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.046 blo = 334, bhi = 1101
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.046 r"""
2025-07-02 06:41:18.046 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.046 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.046 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.046 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046 Example:
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046 >>> d = Differ()
2025-07-02 06:41:18.046 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.046 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.046 >>> print(''.join(results), end="")
2025-07-02 06:41:18.047 - abcDefghiJkl
2025-07-02 06:41:18.047 + abcdefGhijkl
2025-07-02 06:41:18.047 """
2025-07-02 06:41:18.047
2025-07-02 06:41:18.047 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.047 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.047 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.047 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.047 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.047
2025-07-02 06:41:18.047 # search for the pair that matches best without being identical
2025-07-02 06:41:18.047 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.047 # on junk -- unless we have to)
2025-07-02 06:41:18.047 for j in range(blo, bhi):
2025-07-02 06:41:18.047 bj = b[j]
2025-07-02 06:41:18.047 cruncher.set_seq2(bj)
2025-07-02 06:41:18.047 for i in range(alo, ahi):
2025-07-02 06:41:18.047 ai = a[i]
2025-07-02 06:41:18.048 if ai == bj:
2025-07-02 06:41:18.048 if eqi is None:
2025-07-02 06:41:18.048 eqi, eqj = i, j
2025-07-02 06:41:18.048 continue
2025-07-02 06:41:18.048 cruncher.set_seq1(ai)
2025-07-02 06:41:18.048 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.048 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.048 # compares by a factor of 3.
2025-07-02 06:41:18.048 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.048 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.048 # of the computation is cached by cruncher
2025-07-02 06:41:18.048 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.048 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.048 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.048 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.048 if best_ratio < cutoff:
2025-07-02 06:41:18.048 # no non-identical "pretty close" pair
2025-07-02 06:41:18.048 if eqi is None:
2025-07-02 06:41:18.048 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.049 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.049 return
2025-07-02 06:41:18.049 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.049 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.049 else:
2025-07-02 06:41:18.049 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.049 eqi = None
2025-07-02 06:41:18.049
2025-07-02 06:41:18.049 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.049 # identical
2025-07-02 06:41:18.049
2025-07-02 06:41:18.049 # pump out diffs from before the synch point
2025-07-02 06:41:18.049 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.049
2025-07-02 06:41:18.049 # do intraline marking on the synch pair
2025-07-02 06:41:18.049 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.049 if eqi is None:
2025-07-02 06:41:18.049 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.049 atags = btags = ""
2025-07-02 06:41:18.049 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.050 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.050 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.050 if tag == 'replace':
2025-07-02 06:41:18.050 atags += '^' * la
2025-07-02 06:41:18.050 btags += '^' * lb
2025-07-02 06:41:18.050 elif tag == 'delete':
2025-07-02 06:41:18.050 atags += '-' * la
2025-07-02 06:41:18.050 elif tag == 'insert':
2025-07-02 06:41:18.050 btags += '+' * lb
2025-07-02 06:41:18.050 elif tag == 'equal':
2025-07-02 06:41:18.050 atags += ' ' * la
2025-07-02 06:41:18.050 btags += ' ' * lb
2025-07-02 06:41:18.050 else:
2025-07-02 06:41:18.050 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.050 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.050 else:
2025-07-02 06:41:18.050 # the synch pair is identical
2025-07-02 06:41:18.050 yield ' ' + aelt
2025-07-02 06:41:18.050
2025-07-02 06:41:18.050 # pump out diffs from after the synch point
2025-07-02 06:41:18.051 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.051
2025-07-02 06:41:18.051 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.051 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.051
2025-07-02 06:41:18.051 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.051 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.051 alo = 335, ahi = 1101
2025-07-02 06:41:18.051 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.051 blo = 335, bhi = 1101
2025-07-02 06:41:18.051
2025-07-02 06:41:18.051 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.051 g = []
2025-07-02 06:41:18.051 if alo < ahi:
2025-07-02 06:41:18.051 if blo < bhi:
2025-07-02 06:41:18.051 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.051 else:
2025-07-02 06:41:18.051 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.051 elif blo < bhi:
2025-07-02 06:41:18.051 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.051
2025-07-02 06:41:18.052 > yield from g
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.052 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.052 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.052 alo = 335, ahi = 1101
2025-07-02 06:41:18.052 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.052 blo = 335, bhi = 1101
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.052 r"""
2025-07-02 06:41:18.052 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.052 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.052 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.052 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052 Example:
2025-07-02 06:41:18.052
2025-07-02 06:41:18.053 >>> d = Differ()
2025-07-02 06:41:18.053 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.053 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.053 >>> print(''.join(results), end="")
2025-07-02 06:41:18.053 - abcDefghiJkl
2025-07-02 06:41:18.053 + abcdefGhijkl
2025-07-02 06:41:18.053 """
2025-07-02 06:41:18.053
2025-07-02 06:41:18.053 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.053 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.053 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.053 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.053 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.053
2025-07-02 06:41:18.053 # search for the pair that matches best without being identical
2025-07-02 06:41:18.053 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.054 # on junk -- unless we have to)
2025-07-02 06:41:18.054 for j in range(blo, bhi):
2025-07-02 06:41:18.054 bj = b[j]
2025-07-02 06:41:18.054 cruncher.set_seq2(bj)
2025-07-02 06:41:18.054 for i in range(alo, ahi):
2025-07-02 06:41:18.054 ai = a[i]
2025-07-02 06:41:18.054 if ai == bj:
2025-07-02 06:41:18.054 if eqi is None:
2025-07-02 06:41:18.054 eqi, eqj = i, j
2025-07-02 06:41:18.054 continue
2025-07-02 06:41:18.054 cruncher.set_seq1(ai)
2025-07-02 06:41:18.054 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.054 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.054 # compares by a factor of 3.
2025-07-02 06:41:18.054 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.054 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.054 # of the computation is cached by cruncher
2025-07-02 06:41:18.054 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.054 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.055 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.055 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.055 if best_ratio < cutoff:
2025-07-02 06:41:18.055 # no non-identical "pretty close" pair
2025-07-02 06:41:18.055 if eqi is None:
2025-07-02 06:41:18.055 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.055 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.055 return
2025-07-02 06:41:18.055 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.055 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.055 else:
2025-07-02 06:41:18.055 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.055 eqi = None
2025-07-02 06:41:18.055
2025-07-02 06:41:18.055 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.055 # identical
2025-07-02 06:41:18.055
2025-07-02 06:41:18.055 # pump out diffs from before the synch point
2025-07-02 06:41:18.055 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.055
2025-07-02 06:41:18.055 # do intraline marking on the synch pair
2025-07-02 06:41:18.056 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.056 if eqi is None:
2025-07-02 06:41:18.056 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.056 atags = btags = ""
2025-07-02 06:41:18.056 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.056 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.056 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.056 if tag == 'replace':
2025-07-02 06:41:18.056 atags += '^' * la
2025-07-02 06:41:18.056 btags += '^' * lb
2025-07-02 06:41:18.056 elif tag == 'delete':
2025-07-02 06:41:18.056 atags += '-' * la
2025-07-02 06:41:18.056 elif tag == 'insert':
2025-07-02 06:41:18.056 btags += '+' * lb
2025-07-02 06:41:18.056 elif tag == 'equal':
2025-07-02 06:41:18.056 atags += ' ' * la
2025-07-02 06:41:18.056 btags += ' ' * lb
2025-07-02 06:41:18.056 else:
2025-07-02 06:41:18.056 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.057 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.057 else:
2025-07-02 06:41:18.057 # the synch pair is identical
2025-07-02 06:41:18.057 yield ' ' + aelt
2025-07-02 06:41:18.057
2025-07-02 06:41:18.057 # pump out diffs from after the synch point
2025-07-02 06:41:18.057 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.057
2025-07-02 06:41:18.057 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.057 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.057
2025-07-02 06:41:18.057 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.057 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.057 alo = 336, ahi = 1101
2025-07-02 06:41:18.057 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.057 blo = 336, bhi = 1101
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.058 g = []
2025-07-02 06:41:18.058 if alo < ahi:
2025-07-02 06:41:18.058 if blo < bhi:
2025-07-02 06:41:18.058 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.058 else:
2025-07-02 06:41:18.058 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.058 elif blo < bhi:
2025-07-02 06:41:18.058 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 > yield from g
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.058 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.058 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.058 alo = 336, ahi = 1101
2025-07-02 06:41:18.058 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.059 blo = 336, bhi = 1101
2025-07-02 06:41:18.059
2025-07-02 06:41:18.059 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.059 r"""
2025-07-02 06:41:18.059 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.059 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.059 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.059 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.059
2025-07-02 06:41:18.059 Example:
2025-07-02 06:41:18.059
2025-07-02 06:41:18.059 >>> d = Differ()
2025-07-02 06:41:18.059 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.059 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.059 >>> print(''.join(results), end="")
2025-07-02 06:41:18.059 - abcDefghiJkl
2025-07-02 06:41:18.059 + abcdefGhijkl
2025-07-02 06:41:18.060 """
2025-07-02 06:41:18.060
2025-07-02 06:41:18.060 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.060 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.060 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.060 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.060 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.060
2025-07-02 06:41:18.060 # search for the pair that matches best without being identical
2025-07-02 06:41:18.060 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.060 # on junk -- unless we have to)
2025-07-02 06:41:18.060 for j in range(blo, bhi):
2025-07-02 06:41:18.060 bj = b[j]
2025-07-02 06:41:18.060 cruncher.set_seq2(bj)
2025-07-02 06:41:18.060 for i in range(alo, ahi):
2025-07-02 06:41:18.060 ai = a[i]
2025-07-02 06:41:18.060 if ai == bj:
2025-07-02 06:41:18.060 if eqi is None:
2025-07-02 06:41:18.060 eqi, eqj = i, j
2025-07-02 06:41:18.060 continue
2025-07-02 06:41:18.061 cruncher.set_seq1(ai)
2025-07-02 06:41:18.061 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.061 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.061 # compares by a factor of 3.
2025-07-02 06:41:18.061 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.061 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.061 # of the computation is cached by cruncher
2025-07-02 06:41:18.061 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.061 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.061 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.061 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.061 if best_ratio < cutoff:
2025-07-02 06:41:18.061 # no non-identical "pretty close" pair
2025-07-02 06:41:18.061 if eqi is None:
2025-07-02 06:41:18.061 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.061 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.061 return
2025-07-02 06:41:18.061 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.061 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.062 else:
2025-07-02 06:41:18.062 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.062 eqi = None
2025-07-02 06:41:18.062
2025-07-02 06:41:18.062 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.062 # identical
2025-07-02 06:41:18.062
2025-07-02 06:41:18.062 # pump out diffs from before the synch point
2025-07-02 06:41:18.062 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.062
2025-07-02 06:41:18.062 # do intraline marking on the synch pair
2025-07-02 06:41:18.062 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.062 if eqi is None:
2025-07-02 06:41:18.062 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.062 atags = btags = ""
2025-07-02 06:41:18.062 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.062 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.062 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.062 if tag == 'replace':
2025-07-02 06:41:18.063 atags += '^' * la
2025-07-02 06:41:18.063 btags += '^' * lb
2025-07-02 06:41:18.063 elif tag == 'delete':
2025-07-02 06:41:18.063 atags += '-' * la
2025-07-02 06:41:18.063 elif tag == 'insert':
2025-07-02 06:41:18.063 btags += '+' * lb
2025-07-02 06:41:18.063 elif tag == 'equal':
2025-07-02 06:41:18.063 atags += ' ' * la
2025-07-02 06:41:18.063 btags += ' ' * lb
2025-07-02 06:41:18.063 else:
2025-07-02 06:41:18.063 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.063 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.063 else:
2025-07-02 06:41:18.063 # the synch pair is identical
2025-07-02 06:41:18.063 yield ' ' + aelt
2025-07-02 06:41:18.063
2025-07-02 06:41:18.063 # pump out diffs from after the synch point
2025-07-02 06:41:18.063 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.063
2025-07-02 06:41:18.063 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.064 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.064
2025-07-02 06:41:18.064 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.064 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.064 alo = 337, ahi = 1101
2025-07-02 06:41:18.064 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.064 blo = 337, bhi = 1101
2025-07-02 06:41:18.064
2025-07-02 06:41:18.064 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.064 g = []
2025-07-02 06:41:18.064 if alo < ahi:
2025-07-02 06:41:18.064 if blo < bhi:
2025-07-02 06:41:18.064 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.064 else:
2025-07-02 06:41:18.064 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.064 elif blo < bhi:
2025-07-02 06:41:18.064 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.064
2025-07-02 06:41:18.064 > yield from g
2025-07-02 06:41:18.064
2025-07-02 06:41:18.065 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.065 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.065
2025-07-02 06:41:18.065 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.065 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.065 alo = 337, ahi = 1101
2025-07-02 06:41:18.065 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.065 blo = 337, bhi = 1101
2025-07-02 06:41:18.065
2025-07-02 06:41:18.065 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.065 r"""
2025-07-02 06:41:18.065 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.065 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.065 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.065 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.065
2025-07-02 06:41:18.065 Example:
2025-07-02 06:41:18.065
2025-07-02 06:41:18.066 >>> d = Differ()
2025-07-02 06:41:18.066 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.066 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.066 >>> print(''.join(results), end="")
2025-07-02 06:41:18.066 - abcDefghiJkl
2025-07-02 06:41:18.066 + abcdefGhijkl
2025-07-02 06:41:18.066 """
2025-07-02 06:41:18.066
2025-07-02 06:41:18.066 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.066 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.066 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.066 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.066 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.066
2025-07-02 06:41:18.066 # search for the pair that matches best without being identical
2025-07-02 06:41:18.066 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.066 # on junk -- unless we have to)
2025-07-02 06:41:18.067 for j in range(blo, bhi):
2025-07-02 06:41:18.067 bj = b[j]
2025-07-02 06:41:18.067 cruncher.set_seq2(bj)
2025-07-02 06:41:18.067 for i in range(alo, ahi):
2025-07-02 06:41:18.067 ai = a[i]
2025-07-02 06:41:18.067 if ai == bj:
2025-07-02 06:41:18.067 if eqi is None:
2025-07-02 06:41:18.067 eqi, eqj = i, j
2025-07-02 06:41:18.067 continue
2025-07-02 06:41:18.067 cruncher.set_seq1(ai)
2025-07-02 06:41:18.067 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.067 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.067 # compares by a factor of 3.
2025-07-02 06:41:18.067 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.067 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.067 # of the computation is cached by cruncher
2025-07-02 06:41:18.067 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.067 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.067 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.067 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.068 if best_ratio < cutoff:
2025-07-02 06:41:18.068 # no non-identical "pretty close" pair
2025-07-02 06:41:18.068 if eqi is None:
2025-07-02 06:41:18.068 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.068 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.068 return
2025-07-02 06:41:18.068 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.068 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.068 else:
2025-07-02 06:41:18.068 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.068 eqi = None
2025-07-02 06:41:18.068
2025-07-02 06:41:18.068 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.068 # identical
2025-07-02 06:41:18.068
2025-07-02 06:41:18.068 # pump out diffs from before the synch point
2025-07-02 06:41:18.068 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.068
2025-07-02 06:41:18.068 # do intraline marking on the synch pair
2025-07-02 06:41:18.068 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.068 if eqi is None:
2025-07-02 06:41:18.069 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.069 atags = btags = ""
2025-07-02 06:41:18.069 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.069 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.069 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.069 if tag == 'replace':
2025-07-02 06:41:18.069 atags += '^' * la
2025-07-02 06:41:18.069 btags += '^' * lb
2025-07-02 06:41:18.069 elif tag == 'delete':
2025-07-02 06:41:18.069 atags += '-' * la
2025-07-02 06:41:18.069 elif tag == 'insert':
2025-07-02 06:41:18.069 btags += '+' * lb
2025-07-02 06:41:18.069 elif tag == 'equal':
2025-07-02 06:41:18.069 atags += ' ' * la
2025-07-02 06:41:18.069 btags += ' ' * lb
2025-07-02 06:41:18.069 else:
2025-07-02 06:41:18.069 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.069 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.069 else:
2025-07-02 06:41:18.069 # the synch pair is identical
2025-07-02 06:41:18.070 yield ' ' + aelt
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070 # pump out diffs from after the synch point
2025-07-02 06:41:18.070 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.070 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.070 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.070 alo = 338, ahi = 1101
2025-07-02 06:41:18.070 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.070 blo = 338, bhi = 1101
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.070 g = []
2025-07-02 06:41:18.070 if alo < ahi:
2025-07-02 06:41:18.070 if blo < bhi:
2025-07-02 06:41:18.070 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.070 else:
2025-07-02 06:41:18.071 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.071 elif blo < bhi:
2025-07-02 06:41:18.071 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 > yield from g
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.071 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.071 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.071 alo = 338, ahi = 1101
2025-07-02 06:41:18.071 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.071 blo = 338, bhi = 1101
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.071 r"""
2025-07-02 06:41:18.071 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.071 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.071 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.071 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072 Example:
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072 >>> d = Differ()
2025-07-02 06:41:18.072 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.072 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.072 >>> print(''.join(results), end="")
2025-07-02 06:41:18.072 - abcDefghiJkl
2025-07-02 06:41:18.072 + abcdefGhijkl
2025-07-02 06:41:18.072 """
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.072 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.072 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.072 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.072 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072 # search for the pair that matches best without being identical
2025-07-02 06:41:18.073 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.073 # on junk -- unless we have to)
2025-07-02 06:41:18.073 for j in range(blo, bhi):
2025-07-02 06:41:18.073 bj = b[j]
2025-07-02 06:41:18.073 cruncher.set_seq2(bj)
2025-07-02 06:41:18.073 for i in range(alo, ahi):
2025-07-02 06:41:18.073 ai = a[i]
2025-07-02 06:41:18.073 if ai == bj:
2025-07-02 06:41:18.073 if eqi is None:
2025-07-02 06:41:18.073 eqi, eqj = i, j
2025-07-02 06:41:18.073 continue
2025-07-02 06:41:18.073 cruncher.set_seq1(ai)
2025-07-02 06:41:18.073 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.073 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.073 # compares by a factor of 3.
2025-07-02 06:41:18.073 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.073 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.073 # of the computation is cached by cruncher
2025-07-02 06:41:18.074 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.074 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.074 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.074 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.074 if best_ratio < cutoff:
2025-07-02 06:41:18.074 # no non-identical "pretty close" pair
2025-07-02 06:41:18.074 if eqi is None:
2025-07-02 06:41:18.074 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.074 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.074 return
2025-07-02 06:41:18.074 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.074 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.074 else:
2025-07-02 06:41:18.074 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.074 eqi = None
2025-07-02 06:41:18.074
2025-07-02 06:41:18.074 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.074 # identical
2025-07-02 06:41:18.075
2025-07-02 06:41:18.075 # pump out diffs from before the synch point
2025-07-02 06:41:18.075 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.075
2025-07-02 06:41:18.075 # do intraline marking on the synch pair
2025-07-02 06:41:18.075 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.075 if eqi is None:
2025-07-02 06:41:18.075 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.075 atags = btags = ""
2025-07-02 06:41:18.075 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.075 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.075 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.075 if tag == 'replace':
2025-07-02 06:41:18.075 atags += '^' * la
2025-07-02 06:41:18.075 btags += '^' * lb
2025-07-02 06:41:18.075 elif tag == 'delete':
2025-07-02 06:41:18.075 atags += '-' * la
2025-07-02 06:41:18.075 elif tag == 'insert':
2025-07-02 06:41:18.075 btags += '+' * lb
2025-07-02 06:41:18.076 elif tag == 'equal':
2025-07-02 06:41:18.076 atags += ' ' * la
2025-07-02 06:41:18.076 btags += ' ' * lb
2025-07-02 06:41:18.076 else:
2025-07-02 06:41:18.076 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.076 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.076 else:
2025-07-02 06:41:18.076 # the synch pair is identical
2025-07-02 06:41:18.076 yield ' ' + aelt
2025-07-02 06:41:18.076
2025-07-02 06:41:18.076 # pump out diffs from after the synch point
2025-07-02 06:41:18.076 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.076
2025-07-02 06:41:18.076 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.076 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.076
2025-07-02 06:41:18.076 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.076 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.076 alo = 339, ahi = 1101
2025-07-02 06:41:18.076 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.077 blo = 339, bhi = 1101
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.077 g = []
2025-07-02 06:41:18.077 if alo < ahi:
2025-07-02 06:41:18.077 if blo < bhi:
2025-07-02 06:41:18.077 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.077 else:
2025-07-02 06:41:18.077 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.077 elif blo < bhi:
2025-07-02 06:41:18.077 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 > yield from g
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.077 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.077 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.077 alo = 339, ahi = 1101
2025-07-02 06:41:18.078 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.078 blo = 339, bhi = 1101
2025-07-02 06:41:18.078
2025-07-02 06:41:18.078 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.078 r"""
2025-07-02 06:41:18.078 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.078 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.078 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.078 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.078
2025-07-02 06:41:18.078 Example:
2025-07-02 06:41:18.078
2025-07-02 06:41:18.078 >>> d = Differ()
2025-07-02 06:41:18.078 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.078 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.078 >>> print(''.join(results), end="")
2025-07-02 06:41:18.078 - abcDefghiJkl
2025-07-02 06:41:18.078 + abcdefGhijkl
2025-07-02 06:41:18.078 """
2025-07-02 06:41:18.079
2025-07-02 06:41:18.079 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.079 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.079 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.079 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.079 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.079
2025-07-02 06:41:18.079 # search for the pair that matches best without being identical
2025-07-02 06:41:18.079 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.079 # on junk -- unless we have to)
2025-07-02 06:41:18.079 for j in range(blo, bhi):
2025-07-02 06:41:18.079 bj = b[j]
2025-07-02 06:41:18.079 cruncher.set_seq2(bj)
2025-07-02 06:41:18.079 for i in range(alo, ahi):
2025-07-02 06:41:18.079 ai = a[i]
2025-07-02 06:41:18.079 if ai == bj:
2025-07-02 06:41:18.079 if eqi is None:
2025-07-02 06:41:18.079 eqi, eqj = i, j
2025-07-02 06:41:18.079 continue
2025-07-02 06:41:18.079 cruncher.set_seq1(ai)
2025-07-02 06:41:18.080 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.080 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.080 # compares by a factor of 3.
2025-07-02 06:41:18.080 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.080 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.080 # of the computation is cached by cruncher
2025-07-02 06:41:18.080 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.080 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.080 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.080 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.080 if best_ratio < cutoff:
2025-07-02 06:41:18.080 # no non-identical "pretty close" pair
2025-07-02 06:41:18.080 if eqi is None:
2025-07-02 06:41:18.080 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.080 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.080 return
2025-07-02 06:41:18.080 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.080 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.080 else:
2025-07-02 06:41:18.080 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.081 eqi = None
2025-07-02 06:41:18.081
2025-07-02 06:41:18.081 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.081 # identical
2025-07-02 06:41:18.081
2025-07-02 06:41:18.081 # pump out diffs from before the synch point
2025-07-02 06:41:18.081 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.081
2025-07-02 06:41:18.081 # do intraline marking on the synch pair
2025-07-02 06:41:18.081 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.081 if eqi is None:
2025-07-02 06:41:18.081 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.081 atags = btags = ""
2025-07-02 06:41:18.081 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.081 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.081 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.081 if tag == 'replace':
2025-07-02 06:41:18.081 atags += '^' * la
2025-07-02 06:41:18.081 btags += '^' * lb
2025-07-02 06:41:18.081 elif tag == 'delete':
2025-07-02 06:41:18.082 atags += '-' * la
2025-07-02 06:41:18.082 elif tag == 'insert':
2025-07-02 06:41:18.082 btags += '+' * lb
2025-07-02 06:41:18.082 elif tag == 'equal':
2025-07-02 06:41:18.082 atags += ' ' * la
2025-07-02 06:41:18.082 btags += ' ' * lb
2025-07-02 06:41:18.082 else:
2025-07-02 06:41:18.082 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.082 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.082 else:
2025-07-02 06:41:18.082 # the synch pair is identical
2025-07-02 06:41:18.082 yield ' ' + aelt
2025-07-02 06:41:18.082
2025-07-02 06:41:18.082 # pump out diffs from after the synch point
2025-07-02 06:41:18.082 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.082
2025-07-02 06:41:18.082 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.082 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.082
2025-07-02 06:41:18.082 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.083 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.083 alo = 340, ahi = 1101
2025-07-02 06:41:18.083 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.083 blo = 340, bhi = 1101
2025-07-02 06:41:18.083
2025-07-02 06:41:18.083 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.083 g = []
2025-07-02 06:41:18.083 if alo < ahi:
2025-07-02 06:41:18.083 if blo < bhi:
2025-07-02 06:41:18.083 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.083 else:
2025-07-02 06:41:18.083 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.083 elif blo < bhi:
2025-07-02 06:41:18.083 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.083
2025-07-02 06:41:18.083 > yield from g
2025-07-02 06:41:18.083
2025-07-02 06:41:18.084 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.084 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.084 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.084 alo = 340, ahi = 1101
2025-07-02 06:41:18.084 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.084 blo = 340, bhi = 1101
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.084 r"""
2025-07-02 06:41:18.084 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.084 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.084 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.084 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084 Example:
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084 >>> d = Differ()
2025-07-02 06:41:18.085 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.085 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.085 >>> print(''.join(results), end="")
2025-07-02 06:41:18.085 - abcDefghiJkl
2025-07-02 06:41:18.085 + abcdefGhijkl
2025-07-02 06:41:18.085 """
2025-07-02 06:41:18.085
2025-07-02 06:41:18.085 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.085 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.085 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.085 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.085 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.085
2025-07-02 06:41:18.085 # search for the pair that matches best without being identical
2025-07-02 06:41:18.085 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.085 # on junk -- unless we have to)
2025-07-02 06:41:18.085 for j in range(blo, bhi):
2025-07-02 06:41:18.085 bj = b[j]
2025-07-02 06:41:18.086 cruncher.set_seq2(bj)
2025-07-02 06:41:18.086 for i in range(alo, ahi):
2025-07-02 06:41:18.086 ai = a[i]
2025-07-02 06:41:18.086 if ai == bj:
2025-07-02 06:41:18.086 if eqi is None:
2025-07-02 06:41:18.086 eqi, eqj = i, j
2025-07-02 06:41:18.086 continue
2025-07-02 06:41:18.086 cruncher.set_seq1(ai)
2025-07-02 06:41:18.086 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.086 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.086 # compares by a factor of 3.
2025-07-02 06:41:18.086 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.086 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.086 # of the computation is cached by cruncher
2025-07-02 06:41:18.086 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.086 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.086 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.086 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.086 if best_ratio < cutoff:
2025-07-02 06:41:18.086 # no non-identical "pretty close" pair
2025-07-02 06:41:18.087 if eqi is None:
2025-07-02 06:41:18.087 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.087 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.087 return
2025-07-02 06:41:18.087 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.087 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.087 else:
2025-07-02 06:41:18.087 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.087 eqi = None
2025-07-02 06:41:18.087
2025-07-02 06:41:18.087 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.087 # identical
2025-07-02 06:41:18.087
2025-07-02 06:41:18.087 # pump out diffs from before the synch point
2025-07-02 06:41:18.087 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.087
2025-07-02 06:41:18.087 # do intraline marking on the synch pair
2025-07-02 06:41:18.087 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.087 if eqi is None:
2025-07-02 06:41:18.087 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.088 atags = btags = ""
2025-07-02 06:41:18.088 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.088 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.088 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.088 if tag == 'replace':
2025-07-02 06:41:18.088 atags += '^' * la
2025-07-02 06:41:18.088 btags += '^' * lb
2025-07-02 06:41:18.088 elif tag == 'delete':
2025-07-02 06:41:18.088 atags += '-' * la
2025-07-02 06:41:18.088 elif tag == 'insert':
2025-07-02 06:41:18.088 btags += '+' * lb
2025-07-02 06:41:18.088 elif tag == 'equal':
2025-07-02 06:41:18.088 atags += ' ' * la
2025-07-02 06:41:18.088 btags += ' ' * lb
2025-07-02 06:41:18.088 else:
2025-07-02 06:41:18.088 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.088 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.088 else:
2025-07-02 06:41:18.088 # the synch pair is identical
2025-07-02 06:41:18.088 yield ' ' + aelt
2025-07-02 06:41:18.088
2025-07-02 06:41:18.089 # pump out diffs from after the synch point
2025-07-02 06:41:18.089 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.089
2025-07-02 06:41:18.089 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.089 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.089
2025-07-02 06:41:18.089 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.089 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.089 alo = 341, ahi = 1101
2025-07-02 06:41:18.089 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.089 blo = 341, bhi = 1101
2025-07-02 06:41:18.089
2025-07-02 06:41:18.089 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.089 g = []
2025-07-02 06:41:18.089 if alo < ahi:
2025-07-02 06:41:18.089 if blo < bhi:
2025-07-02 06:41:18.089 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.089 else:
2025-07-02 06:41:18.090 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.090 elif blo < bhi:
2025-07-02 06:41:18.090 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 > yield from g
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.090 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.090 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.090 alo = 341, ahi = 1101
2025-07-02 06:41:18.090 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.090 blo = 341, bhi = 1101
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.090 r"""
2025-07-02 06:41:18.090 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.090 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.090 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.091 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.091
2025-07-02 06:41:18.091 Example:
2025-07-02 06:41:18.091
2025-07-02 06:41:18.091 >>> d = Differ()
2025-07-02 06:41:18.091 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.091 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.091 >>> print(''.join(results), end="")
2025-07-02 06:41:18.091 - abcDefghiJkl
2025-07-02 06:41:18.091 + abcdefGhijkl
2025-07-02 06:41:18.091 """
2025-07-02 06:41:18.091
2025-07-02 06:41:18.091 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.091 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.091 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.091 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.091 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.092
2025-07-02 06:41:18.092 # search for the pair that matches best without being identical
2025-07-02 06:41:18.092 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.092 # on junk -- unless we have to)
2025-07-02 06:41:18.092 for j in range(blo, bhi):
2025-07-02 06:41:18.092 bj = b[j]
2025-07-02 06:41:18.092 cruncher.set_seq2(bj)
2025-07-02 06:41:18.092 for i in range(alo, ahi):
2025-07-02 06:41:18.092 ai = a[i]
2025-07-02 06:41:18.092 if ai == bj:
2025-07-02 06:41:18.092 if eqi is None:
2025-07-02 06:41:18.092 eqi, eqj = i, j
2025-07-02 06:41:18.092 continue
2025-07-02 06:41:18.092 cruncher.set_seq1(ai)
2025-07-02 06:41:18.092 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.092 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.092 # compares by a factor of 3.
2025-07-02 06:41:18.092 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.092 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.092 # of the computation is cached by cruncher
2025-07-02 06:41:18.093 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.093 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.093 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.093 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.093 if best_ratio < cutoff:
2025-07-02 06:41:18.093 # no non-identical "pretty close" pair
2025-07-02 06:41:18.093 if eqi is None:
2025-07-02 06:41:18.093 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.093 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.093 return
2025-07-02 06:41:18.093 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.093 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.093 else:
2025-07-02 06:41:18.093 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.093 eqi = None
2025-07-02 06:41:18.093
2025-07-02 06:41:18.093 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.093 # identical
2025-07-02 06:41:18.093
2025-07-02 06:41:18.094 # pump out diffs from before the synch point
2025-07-02 06:41:18.094 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.094
2025-07-02 06:41:18.094 # do intraline marking on the synch pair
2025-07-02 06:41:18.094 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.094 if eqi is None:
2025-07-02 06:41:18.094 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.094 atags = btags = ""
2025-07-02 06:41:18.094 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.094 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.094 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.094 if tag == 'replace':
2025-07-02 06:41:18.094 atags += '^' * la
2025-07-02 06:41:18.094 btags += '^' * lb
2025-07-02 06:41:18.094 elif tag == 'delete':
2025-07-02 06:41:18.094 atags += '-' * la
2025-07-02 06:41:18.094 elif tag == 'insert':
2025-07-02 06:41:18.094 btags += '+' * lb
2025-07-02 06:41:18.094 elif tag == 'equal':
2025-07-02 06:41:18.094 atags += ' ' * la
2025-07-02 06:41:18.095 btags += ' ' * lb
2025-07-02 06:41:18.095 else:
2025-07-02 06:41:18.095 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.095 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.095 else:
2025-07-02 06:41:18.095 # the synch pair is identical
2025-07-02 06:41:18.095 yield ' ' + aelt
2025-07-02 06:41:18.095
2025-07-02 06:41:18.095 # pump out diffs from after the synch point
2025-07-02 06:41:18.095 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.095
2025-07-02 06:41:18.095 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.095 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.095
2025-07-02 06:41:18.095 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.095 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.095 alo = 342, ahi = 1101
2025-07-02 06:41:18.095 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.095 blo = 342, bhi = 1101
2025-07-02 06:41:18.095
2025-07-02 06:41:18.096 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.096 g = []
2025-07-02 06:41:18.096 if alo < ahi:
2025-07-02 06:41:18.096 if blo < bhi:
2025-07-02 06:41:18.096 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.096 else:
2025-07-02 06:41:18.096 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.096 elif blo < bhi:
2025-07-02 06:41:18.096 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.096
2025-07-02 06:41:18.096 > yield from g
2025-07-02 06:41:18.096
2025-07-02 06:41:18.096 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.096 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.096
2025-07-02 06:41:18.096 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.096 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.096 alo = 342, ahi = 1101
2025-07-02 06:41:18.096 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.096 blo = 342, bhi = 1101
2025-07-02 06:41:18.096
2025-07-02 06:41:18.097 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.097 r"""
2025-07-02 06:41:18.097 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.097 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.097 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.097 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.097
2025-07-02 06:41:18.097 Example:
2025-07-02 06:41:18.097
2025-07-02 06:41:18.097 >>> d = Differ()
2025-07-02 06:41:18.097 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.097 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.097 >>> print(''.join(results), end="")
2025-07-02 06:41:18.097 - abcDefghiJkl
2025-07-02 06:41:18.097 + abcdefGhijkl
2025-07-02 06:41:18.097 """
2025-07-02 06:41:18.097
2025-07-02 06:41:18.097 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.098 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.098 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.098 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.098 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.098
2025-07-02 06:41:18.098 # search for the pair that matches best without being identical
2025-07-02 06:41:18.098 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.098 # on junk -- unless we have to)
2025-07-02 06:41:18.098 for j in range(blo, bhi):
2025-07-02 06:41:18.098 bj = b[j]
2025-07-02 06:41:18.098 cruncher.set_seq2(bj)
2025-07-02 06:41:18.098 for i in range(alo, ahi):
2025-07-02 06:41:18.098 ai = a[i]
2025-07-02 06:41:18.098 if ai == bj:
2025-07-02 06:41:18.098 if eqi is None:
2025-07-02 06:41:18.098 eqi, eqj = i, j
2025-07-02 06:41:18.098 continue
2025-07-02 06:41:18.098 cruncher.set_seq1(ai)
2025-07-02 06:41:18.098 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.098 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.099 # compares by a factor of 3.
2025-07-02 06:41:18.099 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.099 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.099 # of the computation is cached by cruncher
2025-07-02 06:41:18.099 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.099 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.099 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.099 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.099 if best_ratio < cutoff:
2025-07-02 06:41:18.099 # no non-identical "pretty close" pair
2025-07-02 06:41:18.099 if eqi is None:
2025-07-02 06:41:18.099 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.099 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.099 return
2025-07-02 06:41:18.099 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.099 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.099 else:
2025-07-02 06:41:18.099 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.099 eqi = None
2025-07-02 06:41:18.099
2025-07-02 06:41:18.099 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.100 # identical
2025-07-02 06:41:18.100
2025-07-02 06:41:18.100 # pump out diffs from before the synch point
2025-07-02 06:41:18.100 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.100
2025-07-02 06:41:18.100 # do intraline marking on the synch pair
2025-07-02 06:41:18.100 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.100 if eqi is None:
2025-07-02 06:41:18.100 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.100 atags = btags = ""
2025-07-02 06:41:18.100 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.100 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.100 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.100 if tag == 'replace':
2025-07-02 06:41:18.100 atags += '^' * la
2025-07-02 06:41:18.100 btags += '^' * lb
2025-07-02 06:41:18.100 elif tag == 'delete':
2025-07-02 06:41:18.100 atags += '-' * la
2025-07-02 06:41:18.100 elif tag == 'insert':
2025-07-02 06:41:18.101 btags += '+' * lb
2025-07-02 06:41:18.101 elif tag == 'equal':
2025-07-02 06:41:18.101 atags += ' ' * la
2025-07-02 06:41:18.101 btags += ' ' * lb
2025-07-02 06:41:18.101 else:
2025-07-02 06:41:18.101 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.101 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.101 else:
2025-07-02 06:41:18.101 # the synch pair is identical
2025-07-02 06:41:18.101 yield ' ' + aelt
2025-07-02 06:41:18.101
2025-07-02 06:41:18.101 # pump out diffs from after the synch point
2025-07-02 06:41:18.101 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.101
2025-07-02 06:41:18.101 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.101 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.101
2025-07-02 06:41:18.101 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.101 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.102 alo = 343, ahi = 1101
2025-07-02 06:41:18.102 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.102 blo = 343, bhi = 1101
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.102 g = []
2025-07-02 06:41:18.102 if alo < ahi:
2025-07-02 06:41:18.102 if blo < bhi:
2025-07-02 06:41:18.102 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.102 else:
2025-07-02 06:41:18.102 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.102 elif blo < bhi:
2025-07-02 06:41:18.102 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 > yield from g
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.102 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.103 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.103 alo = 343, ahi = 1101
2025-07-02 06:41:18.103 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.103 blo = 343, bhi = 1101
2025-07-02 06:41:18.103
2025-07-02 06:41:18.103 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.103 r"""
2025-07-02 06:41:18.103 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.103 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.103 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.103 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.103
2025-07-02 06:41:18.103 Example:
2025-07-02 06:41:18.103
2025-07-02 06:41:18.103 >>> d = Differ()
2025-07-02 06:41:18.103 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.103 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.103 >>> print(''.join(results), end="")
2025-07-02 06:41:18.103 - abcDefghiJkl
2025-07-02 06:41:18.104 + abcdefGhijkl
2025-07-02 06:41:18.104 """
2025-07-02 06:41:18.104
2025-07-02 06:41:18.104 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.104 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.104 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.104 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.104 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.104
2025-07-02 06:41:18.104 # search for the pair that matches best without being identical
2025-07-02 06:41:18.104 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.104 # on junk -- unless we have to)
2025-07-02 06:41:18.104 for j in range(blo, bhi):
2025-07-02 06:41:18.104 bj = b[j]
2025-07-02 06:41:18.104 cruncher.set_seq2(bj)
2025-07-02 06:41:18.104 for i in range(alo, ahi):
2025-07-02 06:41:18.104 ai = a[i]
2025-07-02 06:41:18.104 if ai == bj:
2025-07-02 06:41:18.104 if eqi is None:
2025-07-02 06:41:18.104 eqi, eqj = i, j
2025-07-02 06:41:18.105 continue
2025-07-02 06:41:18.105 cruncher.set_seq1(ai)
2025-07-02 06:41:18.105 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.105 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.105 # compares by a factor of 3.
2025-07-02 06:41:18.105 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.105 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.105 # of the computation is cached by cruncher
2025-07-02 06:41:18.105 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.105 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.105 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.105 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.105 if best_ratio < cutoff:
2025-07-02 06:41:18.105 # no non-identical "pretty close" pair
2025-07-02 06:41:18.105 if eqi is None:
2025-07-02 06:41:18.105 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.105 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.106 return
2025-07-02 06:41:18.106 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.106 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.106 else:
2025-07-02 06:41:18.106 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.106 eqi = None
2025-07-02 06:41:18.106
2025-07-02 06:41:18.106 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.106 # identical
2025-07-02 06:41:18.106
2025-07-02 06:41:18.106 # pump out diffs from before the synch point
2025-07-02 06:41:18.106 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.106
2025-07-02 06:41:18.106 # do intraline marking on the synch pair
2025-07-02 06:41:18.106 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.106 if eqi is None:
2025-07-02 06:41:18.106 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.106 atags = btags = ""
2025-07-02 06:41:18.106 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.106 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.107 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.107 if tag == 'replace':
2025-07-02 06:41:18.107 atags += '^' * la
2025-07-02 06:41:18.107 btags += '^' * lb
2025-07-02 06:41:18.107 elif tag == 'delete':
2025-07-02 06:41:18.107 atags += '-' * la
2025-07-02 06:41:18.107 elif tag == 'insert':
2025-07-02 06:41:18.107 btags += '+' * lb
2025-07-02 06:41:18.107 elif tag == 'equal':
2025-07-02 06:41:18.107 atags += ' ' * la
2025-07-02 06:41:18.107 btags += ' ' * lb
2025-07-02 06:41:18.107 else:
2025-07-02 06:41:18.107 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.107 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.107 else:
2025-07-02 06:41:18.107 # the synch pair is identical
2025-07-02 06:41:18.107 yield ' ' + aelt
2025-07-02 06:41:18.107
2025-07-02 06:41:18.107 # pump out diffs from after the synch point
2025-07-02 06:41:18.107 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.108
2025-07-02 06:41:18.108 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.108 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.108
2025-07-02 06:41:18.108 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.108 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.108 alo = 344, ahi = 1101
2025-07-02 06:41:18.108 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.108 blo = 344, bhi = 1101
2025-07-02 06:41:18.108
2025-07-02 06:41:18.108 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.108 g = []
2025-07-02 06:41:18.108 if alo < ahi:
2025-07-02 06:41:18.108 if blo < bhi:
2025-07-02 06:41:18.108 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.108 else:
2025-07-02 06:41:18.108 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.108 elif blo < bhi:
2025-07-02 06:41:18.108 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 > yield from g
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.109 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.109 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.109 alo = 344, ahi = 1101
2025-07-02 06:41:18.109 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.109 blo = 344, bhi = 1101
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.109 r"""
2025-07-02 06:41:18.109 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.109 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.109 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.109 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.110
2025-07-02 06:41:18.110 Example:
2025-07-02 06:41:18.110
2025-07-02 06:41:18.110 >>> d = Differ()
2025-07-02 06:41:18.110 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.110 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.110 >>> print(''.join(results), end="")
2025-07-02 06:41:18.110 - abcDefghiJkl
2025-07-02 06:41:18.110 + abcdefGhijkl
2025-07-02 06:41:18.110 """
2025-07-02 06:41:18.110
2025-07-02 06:41:18.110 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.110 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.110 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.110 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.110 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.110
2025-07-02 06:41:18.111 # search for the pair that matches best without being identical
2025-07-02 06:41:18.111 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.111 # on junk -- unless we have to)
2025-07-02 06:41:18.111 for j in range(blo, bhi):
2025-07-02 06:41:18.111 bj = b[j]
2025-07-02 06:41:18.111 cruncher.set_seq2(bj)
2025-07-02 06:41:18.111 for i in range(alo, ahi):
2025-07-02 06:41:18.111 ai = a[i]
2025-07-02 06:41:18.111 if ai == bj:
2025-07-02 06:41:18.111 if eqi is None:
2025-07-02 06:41:18.111 eqi, eqj = i, j
2025-07-02 06:41:18.111 continue
2025-07-02 06:41:18.111 cruncher.set_seq1(ai)
2025-07-02 06:41:18.111 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.111 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.111 # compares by a factor of 3.
2025-07-02 06:41:18.111 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.111 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.111 # of the computation is cached by cruncher
2025-07-02 06:41:18.111 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.112 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.112 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.112 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.112 if best_ratio < cutoff:
2025-07-02 06:41:18.112 # no non-identical "pretty close" pair
2025-07-02 06:41:18.112 if eqi is None:
2025-07-02 06:41:18.112 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.112 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.112 return
2025-07-02 06:41:18.112 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.112 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.112 else:
2025-07-02 06:41:18.112 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.112 eqi = None
2025-07-02 06:41:18.112
2025-07-02 06:41:18.112 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.112 # identical
2025-07-02 06:41:18.112
2025-07-02 06:41:18.112 # pump out diffs from before the synch point
2025-07-02 06:41:18.112 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.113
2025-07-02 06:41:18.113 # do intraline marking on the synch pair
2025-07-02 06:41:18.113 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.113 if eqi is None:
2025-07-02 06:41:18.113 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.113 atags = btags = ""
2025-07-02 06:41:18.113 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.113 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.113 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.113 if tag == 'replace':
2025-07-02 06:41:18.113 atags += '^' * la
2025-07-02 06:41:18.113 btags += '^' * lb
2025-07-02 06:41:18.113 elif tag == 'delete':
2025-07-02 06:41:18.113 atags += '-' * la
2025-07-02 06:41:18.113 elif tag == 'insert':
2025-07-02 06:41:18.113 btags += '+' * lb
2025-07-02 06:41:18.113 elif tag == 'equal':
2025-07-02 06:41:18.113 atags += ' ' * la
2025-07-02 06:41:18.113 btags += ' ' * lb
2025-07-02 06:41:18.113 else:
2025-07-02 06:41:18.114 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.114 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.114 else:
2025-07-02 06:41:18.114 # the synch pair is identical
2025-07-02 06:41:18.114 yield ' ' + aelt
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114 # pump out diffs from after the synch point
2025-07-02 06:41:18.114 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.114 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.114 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.114 alo = 345, ahi = 1101
2025-07-02 06:41:18.114 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.114 blo = 345, bhi = 1101
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.115 g = []
2025-07-02 06:41:18.115 if alo < ahi:
2025-07-02 06:41:18.115 if blo < bhi:
2025-07-02 06:41:18.115 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.115 else:
2025-07-02 06:41:18.115 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.115 elif blo < bhi:
2025-07-02 06:41:18.115 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.115
2025-07-02 06:41:18.115 > yield from g
2025-07-02 06:41:18.115
2025-07-02 06:41:18.115 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.115 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.115
2025-07-02 06:41:18.115 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.115 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.115 alo = 345, ahi = 1101
2025-07-02 06:41:18.115 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.115 blo = 345, bhi = 1101
2025-07-02 06:41:18.115
2025-07-02 06:41:18.116 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.116 r"""
2025-07-02 06:41:18.116 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.116 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.116 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.116 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.116
2025-07-02 06:41:18.116 Example:
2025-07-02 06:41:18.116
2025-07-02 06:41:18.116 >>> d = Differ()
2025-07-02 06:41:18.116 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.116 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.116 >>> print(''.join(results), end="")
2025-07-02 06:41:18.116 - abcDefghiJkl
2025-07-02 06:41:18.116 + abcdefGhijkl
2025-07-02 06:41:18.116 """
2025-07-02 06:41:18.116
2025-07-02 06:41:18.116 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.116 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.117 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.117 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.117 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.117
2025-07-02 06:41:18.117 # search for the pair that matches best without being identical
2025-07-02 06:41:18.117 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.117 # on junk -- unless we have to)
2025-07-02 06:41:18.117 for j in range(blo, bhi):
2025-07-02 06:41:18.117 bj = b[j]
2025-07-02 06:41:18.117 cruncher.set_seq2(bj)
2025-07-02 06:41:18.117 for i in range(alo, ahi):
2025-07-02 06:41:18.117 ai = a[i]
2025-07-02 06:41:18.117 if ai == bj:
2025-07-02 06:41:18.117 if eqi is None:
2025-07-02 06:41:18.117 eqi, eqj = i, j
2025-07-02 06:41:18.117 continue
2025-07-02 06:41:18.117 cruncher.set_seq1(ai)
2025-07-02 06:41:18.117 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.117 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.117 # compares by a factor of 3.
2025-07-02 06:41:18.118 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.118 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.118 # of the computation is cached by cruncher
2025-07-02 06:41:18.118 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.118 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.118 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.118 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.118 if best_ratio < cutoff:
2025-07-02 06:41:18.118 # no non-identical "pretty close" pair
2025-07-02 06:41:18.118 if eqi is None:
2025-07-02 06:41:18.118 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.118 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.118 return
2025-07-02 06:41:18.118 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.118 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.118 else:
2025-07-02 06:41:18.118 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.119 eqi = None
2025-07-02 06:41:18.119
2025-07-02 06:41:18.119 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.119 # identical
2025-07-02 06:41:18.119
2025-07-02 06:41:18.119 # pump out diffs from before the synch point
2025-07-02 06:41:18.119 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.119
2025-07-02 06:41:18.119 # do intraline marking on the synch pair
2025-07-02 06:41:18.119 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.119 if eqi is None:
2025-07-02 06:41:18.119 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.119 atags = btags = ""
2025-07-02 06:41:18.119 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.119 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.119 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.119 if tag == 'replace':
2025-07-02 06:41:18.119 atags += '^' * la
2025-07-02 06:41:18.119 btags += '^' * lb
2025-07-02 06:41:18.120 elif tag == 'delete':
2025-07-02 06:41:18.120 atags += '-' * la
2025-07-02 06:41:18.120 elif tag == 'insert':
2025-07-02 06:41:18.120 btags += '+' * lb
2025-07-02 06:41:18.120 elif tag == 'equal':
2025-07-02 06:41:18.120 atags += ' ' * la
2025-07-02 06:41:18.120 btags += ' ' * lb
2025-07-02 06:41:18.120 else:
2025-07-02 06:41:18.120 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.120 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.120 else:
2025-07-02 06:41:18.120 # the synch pair is identical
2025-07-02 06:41:18.120 yield ' ' + aelt
2025-07-02 06:41:18.120
2025-07-02 06:41:18.120 # pump out diffs from after the synch point
2025-07-02 06:41:18.120 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.120
2025-07-02 06:41:18.120 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.120
2025-07-02 06:41:18.121 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.121 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.121 alo = 346, ahi = 1101
2025-07-02 06:41:18.121 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.121 blo = 346, bhi = 1101
2025-07-02 06:41:18.121
2025-07-02 06:41:18.121 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.121 g = []
2025-07-02 06:41:18.121 if alo < ahi:
2025-07-02 06:41:18.121 if blo < bhi:
2025-07-02 06:41:18.121 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.121 else:
2025-07-02 06:41:18.121 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.121 elif blo < bhi:
2025-07-02 06:41:18.121 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.121
2025-07-02 06:41:18.121 > yield from g
2025-07-02 06:41:18.121
2025-07-02 06:41:18.122 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.122 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.122 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.122 alo = 346, ahi = 1101
2025-07-02 06:41:18.122 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.122 blo = 346, bhi = 1101
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.122 r"""
2025-07-02 06:41:18.122 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.122 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.122 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.122 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122 Example:
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122 >>> d = Differ()
2025-07-02 06:41:18.123 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.123 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.123 >>> print(''.join(results), end="")
2025-07-02 06:41:18.123 - abcDefghiJkl
2025-07-02 06:41:18.123 + abcdefGhijkl
2025-07-02 06:41:18.123 """
2025-07-02 06:41:18.123
2025-07-02 06:41:18.123 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.123 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.123 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.123 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.123 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.123
2025-07-02 06:41:18.123 # search for the pair that matches best without being identical
2025-07-02 06:41:18.123 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.123 # on junk -- unless we have to)
2025-07-02 06:41:18.123 for j in range(blo, bhi):
2025-07-02 06:41:18.123 bj = b[j]
2025-07-02 06:41:18.124 cruncher.set_seq2(bj)
2025-07-02 06:41:18.124 for i in range(alo, ahi):
2025-07-02 06:41:18.124 ai = a[i]
2025-07-02 06:41:18.124 if ai == bj:
2025-07-02 06:41:18.124 if eqi is None:
2025-07-02 06:41:18.124 eqi, eqj = i, j
2025-07-02 06:41:18.124 continue
2025-07-02 06:41:18.124 cruncher.set_seq1(ai)
2025-07-02 06:41:18.124 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.124 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.124 # compares by a factor of 3.
2025-07-02 06:41:18.124 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.124 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.124 # of the computation is cached by cruncher
2025-07-02 06:41:18.124 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.124 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.124 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.124 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.124 if best_ratio < cutoff:
2025-07-02 06:41:18.124 # no non-identical "pretty close" pair
2025-07-02 06:41:18.125 if eqi is None:
2025-07-02 06:41:18.125 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.125 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.125 return
2025-07-02 06:41:18.125 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.125 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.125 else:
2025-07-02 06:41:18.125 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.125 eqi = None
2025-07-02 06:41:18.125
2025-07-02 06:41:18.125 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.125 # identical
2025-07-02 06:41:18.125
2025-07-02 06:41:18.125 # pump out diffs from before the synch point
2025-07-02 06:41:18.125 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.125
2025-07-02 06:41:18.125 # do intraline marking on the synch pair
2025-07-02 06:41:18.125 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.125 if eqi is None:
2025-07-02 06:41:18.125 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.126 atags = btags = ""
2025-07-02 06:41:18.126 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.126 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.126 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.126 if tag == 'replace':
2025-07-02 06:41:18.126 atags += '^' * la
2025-07-02 06:41:18.126 btags += '^' * lb
2025-07-02 06:41:18.126 elif tag == 'delete':
2025-07-02 06:41:18.126 atags += '-' * la
2025-07-02 06:41:18.126 elif tag == 'insert':
2025-07-02 06:41:18.126 btags += '+' * lb
2025-07-02 06:41:18.126 elif tag == 'equal':
2025-07-02 06:41:18.126 atags += ' ' * la
2025-07-02 06:41:18.126 btags += ' ' * lb
2025-07-02 06:41:18.126 else:
2025-07-02 06:41:18.126 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.126 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.126 else:
2025-07-02 06:41:18.126 # the synch pair is identical
2025-07-02 06:41:18.126 yield ' ' + aelt
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127 # pump out diffs from after the synch point
2025-07-02 06:41:18.127 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.127 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.127 alo = 347, ahi = 1101
2025-07-02 06:41:18.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.127 blo = 347, bhi = 1101
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.127 g = []
2025-07-02 06:41:18.127 if alo < ahi:
2025-07-02 06:41:18.127 if blo < bhi:
2025-07-02 06:41:18.128 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.128 else:
2025-07-02 06:41:18.128 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.128 elif blo < bhi:
2025-07-02 06:41:18.128 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 > yield from g
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.128 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.128 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.128 alo = 347, ahi = 1101
2025-07-02 06:41:18.128 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.128 blo = 347, bhi = 1101
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.128 r"""
2025-07-02 06:41:18.129 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.129 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.129 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.129 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.129
2025-07-02 06:41:18.129 Example:
2025-07-02 06:41:18.129
2025-07-02 06:41:18.129 >>> d = Differ()
2025-07-02 06:41:18.129 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.129 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.129 >>> print(''.join(results), end="")
2025-07-02 06:41:18.129 - abcDefghiJkl
2025-07-02 06:41:18.129 + abcdefGhijkl
2025-07-02 06:41:18.129 """
2025-07-02 06:41:18.129
2025-07-02 06:41:18.129 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.129 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.129 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.129 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.130 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.130
2025-07-02 06:41:18.130 # search for the pair that matches best without being identical
2025-07-02 06:41:18.130 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.130 # on junk -- unless we have to)
2025-07-02 06:41:18.130 for j in range(blo, bhi):
2025-07-02 06:41:18.130 bj = b[j]
2025-07-02 06:41:18.130 cruncher.set_seq2(bj)
2025-07-02 06:41:18.130 for i in range(alo, ahi):
2025-07-02 06:41:18.130 ai = a[i]
2025-07-02 06:41:18.130 if ai == bj:
2025-07-02 06:41:18.130 if eqi is None:
2025-07-02 06:41:18.130 eqi, eqj = i, j
2025-07-02 06:41:18.130 continue
2025-07-02 06:41:18.130 cruncher.set_seq1(ai)
2025-07-02 06:41:18.130 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.130 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.130 # compares by a factor of 3.
2025-07-02 06:41:18.130 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.130 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.131 # of the computation is cached by cruncher
2025-07-02 06:41:18.131 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.131 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.131 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.131 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.131 if best_ratio < cutoff:
2025-07-02 06:41:18.131 # no non-identical "pretty close" pair
2025-07-02 06:41:18.131 if eqi is None:
2025-07-02 06:41:18.131 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.131 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.131 return
2025-07-02 06:41:18.131 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.131 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.131 else:
2025-07-02 06:41:18.131 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.131 eqi = None
2025-07-02 06:41:18.131
2025-07-02 06:41:18.131 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.131 # identical
2025-07-02 06:41:18.131
2025-07-02 06:41:18.132 # pump out diffs from before the synch point
2025-07-02 06:41:18.132 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.132
2025-07-02 06:41:18.132 # do intraline marking on the synch pair
2025-07-02 06:41:18.132 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.132 if eqi is None:
2025-07-02 06:41:18.132 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.132 atags = btags = ""
2025-07-02 06:41:18.132 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.132 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.132 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.132 if tag == 'replace':
2025-07-02 06:41:18.132 atags += '^' * la
2025-07-02 06:41:18.132 btags += '^' * lb
2025-07-02 06:41:18.132 elif tag == 'delete':
2025-07-02 06:41:18.132 atags += '-' * la
2025-07-02 06:41:18.132 elif tag == 'insert':
2025-07-02 06:41:18.132 btags += '+' * lb
2025-07-02 06:41:18.132 elif tag == 'equal':
2025-07-02 06:41:18.132 atags += ' ' * la
2025-07-02 06:41:18.132 btags += ' ' * lb
2025-07-02 06:41:18.133 else:
2025-07-02 06:41:18.133 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.133 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.133 else:
2025-07-02 06:41:18.133 # the synch pair is identical
2025-07-02 06:41:18.133 yield ' ' + aelt
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133 # pump out diffs from after the synch point
2025-07-02 06:41:18.133 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.133 alo = 348, ahi = 1101
2025-07-02 06:41:18.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.133 blo = 348, bhi = 1101
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.134 g = []
2025-07-02 06:41:18.134 if alo < ahi:
2025-07-02 06:41:18.134 if blo < bhi:
2025-07-02 06:41:18.134 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.134 else:
2025-07-02 06:41:18.134 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.134 elif blo < bhi:
2025-07-02 06:41:18.134 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.134
2025-07-02 06:41:18.134 > yield from g
2025-07-02 06:41:18.134
2025-07-02 06:41:18.134 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.134 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.134
2025-07-02 06:41:18.134 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.134 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.134 alo = 348, ahi = 1101
2025-07-02 06:41:18.134 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.134 blo = 348, bhi = 1101
2025-07-02 06:41:18.134
2025-07-02 06:41:18.135 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.135 r"""
2025-07-02 06:41:18.135 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.135 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.135 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.135 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.135
2025-07-02 06:41:18.135 Example:
2025-07-02 06:41:18.135
2025-07-02 06:41:18.135 >>> d = Differ()
2025-07-02 06:41:18.135 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.135 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.135 >>> print(''.join(results), end="")
2025-07-02 06:41:18.135 - abcDefghiJkl
2025-07-02 06:41:18.135 + abcdefGhijkl
2025-07-02 06:41:18.135 """
2025-07-02 06:41:18.136
2025-07-02 06:41:18.136 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.136 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.136 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.136 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.136 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.136
2025-07-02 06:41:18.136 # search for the pair that matches best without being identical
2025-07-02 06:41:18.136 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.136 # on junk -- unless we have to)
2025-07-02 06:41:18.136 for j in range(blo, bhi):
2025-07-02 06:41:18.136 bj = b[j]
2025-07-02 06:41:18.136 cruncher.set_seq2(bj)
2025-07-02 06:41:18.136 for i in range(alo, ahi):
2025-07-02 06:41:18.136 ai = a[i]
2025-07-02 06:41:18.136 if ai == bj:
2025-07-02 06:41:18.136 if eqi is None:
2025-07-02 06:41:18.136 eqi, eqj = i, j
2025-07-02 06:41:18.136 continue
2025-07-02 06:41:18.137 cruncher.set_seq1(ai)
2025-07-02 06:41:18.137 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.137 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.137 # compares by a factor of 3.
2025-07-02 06:41:18.137 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.137 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.137 # of the computation is cached by cruncher
2025-07-02 06:41:18.137 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.137 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.137 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.137 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.137 if best_ratio < cutoff:
2025-07-02 06:41:18.137 # no non-identical "pretty close" pair
2025-07-02 06:41:18.137 if eqi is None:
2025-07-02 06:41:18.137 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.137 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.137 return
2025-07-02 06:41:18.137 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.137 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.138 else:
2025-07-02 06:41:18.138 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.138 eqi = None
2025-07-02 06:41:18.138
2025-07-02 06:41:18.138 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.138 # identical
2025-07-02 06:41:18.138
2025-07-02 06:41:18.138 # pump out diffs from before the synch point
2025-07-02 06:41:18.138 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.138
2025-07-02 06:41:18.138 # do intraline marking on the synch pair
2025-07-02 06:41:18.138 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.138 if eqi is None:
2025-07-02 06:41:18.138 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.138 atags = btags = ""
2025-07-02 06:41:18.138 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.138 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.138 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.138 if tag == 'replace':
2025-07-02 06:41:18.138 atags += '^' * la
2025-07-02 06:41:18.139 btags += '^' * lb
2025-07-02 06:41:18.139 elif tag == 'delete':
2025-07-02 06:41:18.139 atags += '-' * la
2025-07-02 06:41:18.139 elif tag == 'insert':
2025-07-02 06:41:18.139 btags += '+' * lb
2025-07-02 06:41:18.139 elif tag == 'equal':
2025-07-02 06:41:18.139 atags += ' ' * la
2025-07-02 06:41:18.139 btags += ' ' * lb
2025-07-02 06:41:18.139 else:
2025-07-02 06:41:18.139 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.139 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.139 else:
2025-07-02 06:41:18.139 # the synch pair is identical
2025-07-02 06:41:18.139 yield ' ' + aelt
2025-07-02 06:41:18.139
2025-07-02 06:41:18.139 # pump out diffs from after the synch point
2025-07-02 06:41:18.139 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.139
2025-07-02 06:41:18.139 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.139
2025-07-02 06:41:18.139 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.140 alo = 349, ahi = 1101
2025-07-02 06:41:18.140 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.140 blo = 349, bhi = 1101
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.140 g = []
2025-07-02 06:41:18.140 if alo < ahi:
2025-07-02 06:41:18.140 if blo < bhi:
2025-07-02 06:41:18.140 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.140 else:
2025-07-02 06:41:18.140 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.140 elif blo < bhi:
2025-07-02 06:41:18.140 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 > yield from g
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.140 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.140 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.141 alo = 349, ahi = 1101
2025-07-02 06:41:18.141 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.141 blo = 349, bhi = 1101
2025-07-02 06:41:18.141
2025-07-02 06:41:18.141 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.141 r"""
2025-07-02 06:41:18.141 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.141 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.141 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.141 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.141
2025-07-02 06:41:18.141 Example:
2025-07-02 06:41:18.141
2025-07-02 06:41:18.141 >>> d = Differ()
2025-07-02 06:41:18.141 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.141 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.141 >>> print(''.join(results), end="")
2025-07-02 06:41:18.141 - abcDefghiJkl
2025-07-02 06:41:18.141 + abcdefGhijkl
2025-07-02 06:41:18.142 """
2025-07-02 06:41:18.142
2025-07-02 06:41:18.142 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.142 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.142 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.142 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.142 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.142
2025-07-02 06:41:18.142 # search for the pair that matches best without being identical
2025-07-02 06:41:18.142 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.142 # on junk -- unless we have to)
2025-07-02 06:41:18.142 for j in range(blo, bhi):
2025-07-02 06:41:18.142 bj = b[j]
2025-07-02 06:41:18.142 cruncher.set_seq2(bj)
2025-07-02 06:41:18.142 for i in range(alo, ahi):
2025-07-02 06:41:18.142 ai = a[i]
2025-07-02 06:41:18.142 if ai == bj:
2025-07-02 06:41:18.142 if eqi is None:
2025-07-02 06:41:18.142 eqi, eqj = i, j
2025-07-02 06:41:18.143 continue
2025-07-02 06:41:18.143 cruncher.set_seq1(ai)
2025-07-02 06:41:18.143 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.143 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.143 # compares by a factor of 3.
2025-07-02 06:41:18.143 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.143 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.143 # of the computation is cached by cruncher
2025-07-02 06:41:18.143 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.143 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.143 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.143 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.143 if best_ratio < cutoff:
2025-07-02 06:41:18.143 # no non-identical "pretty close" pair
2025-07-02 06:41:18.143 if eqi is None:
2025-07-02 06:41:18.143 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.143 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.143 return
2025-07-02 06:41:18.143 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.143 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.144 else:
2025-07-02 06:41:18.144 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.144 eqi = None
2025-07-02 06:41:18.144
2025-07-02 06:41:18.144 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.144 # identical
2025-07-02 06:41:18.144
2025-07-02 06:41:18.144 # pump out diffs from before the synch point
2025-07-02 06:41:18.144 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.144
2025-07-02 06:41:18.144 # do intraline marking on the synch pair
2025-07-02 06:41:18.144 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.144 if eqi is None:
2025-07-02 06:41:18.144 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.144 atags = btags = ""
2025-07-02 06:41:18.144 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.144 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.144 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.145 if tag == 'replace':
2025-07-02 06:41:18.145 atags += '^' * la
2025-07-02 06:41:18.145 btags += '^' * lb
2025-07-02 06:41:18.145 elif tag == 'delete':
2025-07-02 06:41:18.145 atags += '-' * la
2025-07-02 06:41:18.145 elif tag == 'insert':
2025-07-02 06:41:18.145 btags += '+' * lb
2025-07-02 06:41:18.145 elif tag == 'equal':
2025-07-02 06:41:18.145 atags += ' ' * la
2025-07-02 06:41:18.145 btags += ' ' * lb
2025-07-02 06:41:18.145 else:
2025-07-02 06:41:18.145 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.145 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.145 else:
2025-07-02 06:41:18.145 # the synch pair is identical
2025-07-02 06:41:18.145 yield ' ' + aelt
2025-07-02 06:41:18.145
2025-07-02 06:41:18.145 # pump out diffs from after the synch point
2025-07-02 06:41:18.145 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.145
2025-07-02 06:41:18.146 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.146 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.146
2025-07-02 06:41:18.146 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.146 alo = 350, ahi = 1101
2025-07-02 06:41:18.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.146 blo = 350, bhi = 1101
2025-07-02 06:41:18.146
2025-07-02 06:41:18.146 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.146 g = []
2025-07-02 06:41:18.146 if alo < ahi:
2025-07-02 06:41:18.146 if blo < bhi:
2025-07-02 06:41:18.146 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.146 else:
2025-07-02 06:41:18.146 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.146 elif blo < bhi:
2025-07-02 06:41:18.146 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.146
2025-07-02 06:41:18.147 > yield from g
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.147 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.147 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.147 alo = 350, ahi = 1101
2025-07-02 06:41:18.147 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.147 blo = 350, bhi = 1101
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.147 r"""
2025-07-02 06:41:18.147 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.147 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.147 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.147 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147 Example:
2025-07-02 06:41:18.148
2025-07-02 06:41:18.148 >>> d = Differ()
2025-07-02 06:41:18.148 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.148 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.148 >>> print(''.join(results), end="")
2025-07-02 06:41:18.148 - abcDefghiJkl
2025-07-02 06:41:18.148 + abcdefGhijkl
2025-07-02 06:41:18.148 """
2025-07-02 06:41:18.148
2025-07-02 06:41:18.148 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.148 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.148 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.148 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.148 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.148
2025-07-02 06:41:18.148 # search for the pair that matches best without being identical
2025-07-02 06:41:18.148 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.148 # on junk -- unless we have to)
2025-07-02 06:41:18.149 for j in range(blo, bhi):
2025-07-02 06:41:18.149 bj = b[j]
2025-07-02 06:41:18.149 cruncher.set_seq2(bj)
2025-07-02 06:41:18.149 for i in range(alo, ahi):
2025-07-02 06:41:18.149 ai = a[i]
2025-07-02 06:41:18.149 if ai == bj:
2025-07-02 06:41:18.149 if eqi is None:
2025-07-02 06:41:18.149 eqi, eqj = i, j
2025-07-02 06:41:18.149 continue
2025-07-02 06:41:18.149 cruncher.set_seq1(ai)
2025-07-02 06:41:18.149 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.149 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.149 # compares by a factor of 3.
2025-07-02 06:41:18.149 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.149 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.149 # of the computation is cached by cruncher
2025-07-02 06:41:18.149 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.149 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.149 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.150 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.150 if best_ratio < cutoff:
2025-07-02 06:41:18.150 # no non-identical "pretty close" pair
2025-07-02 06:41:18.150 if eqi is None:
2025-07-02 06:41:18.150 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.150 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.150 return
2025-07-02 06:41:18.150 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.150 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.150 else:
2025-07-02 06:41:18.150 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.150 eqi = None
2025-07-02 06:41:18.150
2025-07-02 06:41:18.150 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.150 # identical
2025-07-02 06:41:18.150
2025-07-02 06:41:18.150 # pump out diffs from before the synch point
2025-07-02 06:41:18.150 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.150
2025-07-02 06:41:18.150 # do intraline marking on the synch pair
2025-07-02 06:41:18.151 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.151 if eqi is None:
2025-07-02 06:41:18.151 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.151 atags = btags = ""
2025-07-02 06:41:18.151 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.151 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.151 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.151 if tag == 'replace':
2025-07-02 06:41:18.151 atags += '^' * la
2025-07-02 06:41:18.151 btags += '^' * lb
2025-07-02 06:41:18.151 elif tag == 'delete':
2025-07-02 06:41:18.151 atags += '-' * la
2025-07-02 06:41:18.151 elif tag == 'insert':
2025-07-02 06:41:18.151 btags += '+' * lb
2025-07-02 06:41:18.151 elif tag == 'equal':
2025-07-02 06:41:18.151 atags += ' ' * la
2025-07-02 06:41:18.151 btags += ' ' * lb
2025-07-02 06:41:18.151 else:
2025-07-02 06:41:18.151 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.152 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.152 else:
2025-07-02 06:41:18.152 # the synch pair is identical
2025-07-02 06:41:18.152 yield ' ' + aelt
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152 # pump out diffs from after the synch point
2025-07-02 06:41:18.152 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.152 alo = 351, ahi = 1101
2025-07-02 06:41:18.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.152 blo = 351, bhi = 1101
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.152 g = []
2025-07-02 06:41:18.153 if alo < ahi:
2025-07-02 06:41:18.153 if blo < bhi:
2025-07-02 06:41:18.153 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.153 else:
2025-07-02 06:41:18.153 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.153 elif blo < bhi:
2025-07-02 06:41:18.153 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.153
2025-07-02 06:41:18.153 > yield from g
2025-07-02 06:41:18.153
2025-07-02 06:41:18.153 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.153 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.153
2025-07-02 06:41:18.153 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.153 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.153 alo = 351, ahi = 1101
2025-07-02 06:41:18.153 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.153 blo = 351, bhi = 1101
2025-07-02 06:41:18.154
2025-07-02 06:41:18.154 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.154 r"""
2025-07-02 06:41:18.154 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.154 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.154 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.154 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.154
2025-07-02 06:41:18.154 Example:
2025-07-02 06:41:18.154
2025-07-02 06:41:18.154 >>> d = Differ()
2025-07-02 06:41:18.154 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.154 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.154 >>> print(''.join(results), end="")
2025-07-02 06:41:18.154 - abcDefghiJkl
2025-07-02 06:41:18.154 + abcdefGhijkl
2025-07-02 06:41:18.154 """
2025-07-02 06:41:18.154
2025-07-02 06:41:18.155 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.155 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.155 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.155 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.155 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.155
2025-07-02 06:41:18.155 # search for the pair that matches best without being identical
2025-07-02 06:41:18.155 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.155 # on junk -- unless we have to)
2025-07-02 06:41:18.155 for j in range(blo, bhi):
2025-07-02 06:41:18.155 bj = b[j]
2025-07-02 06:41:18.155 cruncher.set_seq2(bj)
2025-07-02 06:41:18.155 for i in range(alo, ahi):
2025-07-02 06:41:18.155 ai = a[i]
2025-07-02 06:41:18.155 if ai == bj:
2025-07-02 06:41:18.155 if eqi is None:
2025-07-02 06:41:18.155 eqi, eqj = i, j
2025-07-02 06:41:18.155 continue
2025-07-02 06:41:18.155 cruncher.set_seq1(ai)
2025-07-02 06:41:18.155 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.156 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.156 # compares by a factor of 3.
2025-07-02 06:41:18.156 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.156 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.156 # of the computation is cached by cruncher
2025-07-02 06:41:18.156 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.156 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.156 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.156 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.156 if best_ratio < cutoff:
2025-07-02 06:41:18.156 # no non-identical "pretty close" pair
2025-07-02 06:41:18.156 if eqi is None:
2025-07-02 06:41:18.156 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.156 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.156 return
2025-07-02 06:41:18.156 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.156 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.156 else:
2025-07-02 06:41:18.156 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.157 eqi = None
2025-07-02 06:41:18.157
2025-07-02 06:41:18.157 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.157 # identical
2025-07-02 06:41:18.157
2025-07-02 06:41:18.157 # pump out diffs from before the synch point
2025-07-02 06:41:18.157 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.157
2025-07-02 06:41:18.157 # do intraline marking on the synch pair
2025-07-02 06:41:18.157 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.157 if eqi is None:
2025-07-02 06:41:18.157 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.157 atags = btags = ""
2025-07-02 06:41:18.157 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.157 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.157 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.157 if tag == 'replace':
2025-07-02 06:41:18.157 atags += '^' * la
2025-07-02 06:41:18.157 btags += '^' * lb
2025-07-02 06:41:18.157 elif tag == 'delete':
2025-07-02 06:41:18.158 atags += '-' * la
2025-07-02 06:41:18.158 elif tag == 'insert':
2025-07-02 06:41:18.158 btags += '+' * lb
2025-07-02 06:41:18.158 elif tag == 'equal':
2025-07-02 06:41:18.158 atags += ' ' * la
2025-07-02 06:41:18.158 btags += ' ' * lb
2025-07-02 06:41:18.158 else:
2025-07-02 06:41:18.158 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.158 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.158 else:
2025-07-02 06:41:18.158 # the synch pair is identical
2025-07-02 06:41:18.158 yield ' ' + aelt
2025-07-02 06:41:18.158
2025-07-02 06:41:18.158 # pump out diffs from after the synch point
2025-07-02 06:41:18.158 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.158
2025-07-02 06:41:18.158 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.158
2025-07-02 06:41:18.159 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.159 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.159 alo = 352, ahi = 1101
2025-07-02 06:41:18.159 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.159 blo = 352, bhi = 1101
2025-07-02 06:41:18.159
2025-07-02 06:41:18.159 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.159 g = []
2025-07-02 06:41:18.159 if alo < ahi:
2025-07-02 06:41:18.159 if blo < bhi:
2025-07-02 06:41:18.159 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.159 else:
2025-07-02 06:41:18.159 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.159 elif blo < bhi:
2025-07-02 06:41:18.159 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.159
2025-07-02 06:41:18.159 > yield from g
2025-07-02 06:41:18.159
2025-07-02 06:41:18.159 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.159 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.160 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.160 alo = 352, ahi = 1101
2025-07-02 06:41:18.160 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.160 blo = 352, bhi = 1101
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.160 r"""
2025-07-02 06:41:18.160 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.160 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.160 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.160 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160 Example:
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160 >>> d = Differ()
2025-07-02 06:41:18.160 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.160 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.161 >>> print(''.join(results), end="")
2025-07-02 06:41:18.161 - abcDefghiJkl
2025-07-02 06:41:18.161 + abcdefGhijkl
2025-07-02 06:41:18.161 """
2025-07-02 06:41:18.161
2025-07-02 06:41:18.161 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.161 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.161 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.161 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.161 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.161
2025-07-02 06:41:18.161 # search for the pair that matches best without being identical
2025-07-02 06:41:18.161 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.161 # on junk -- unless we have to)
2025-07-02 06:41:18.161 for j in range(blo, bhi):
2025-07-02 06:41:18.161 bj = b[j]
2025-07-02 06:41:18.161 cruncher.set_seq2(bj)
2025-07-02 06:41:18.161 for i in range(alo, ahi):
2025-07-02 06:41:18.162 ai = a[i]
2025-07-02 06:41:18.162 if ai == bj:
2025-07-02 06:41:18.162 if eqi is None:
2025-07-02 06:41:18.162 eqi, eqj = i, j
2025-07-02 06:41:18.162 continue
2025-07-02 06:41:18.162 cruncher.set_seq1(ai)
2025-07-02 06:41:18.162 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.162 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.162 # compares by a factor of 3.
2025-07-02 06:41:18.162 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.162 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.162 # of the computation is cached by cruncher
2025-07-02 06:41:18.162 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.162 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.162 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.162 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.162 if best_ratio < cutoff:
2025-07-02 06:41:18.162 # no non-identical "pretty close" pair
2025-07-02 06:41:18.162 if eqi is None:
2025-07-02 06:41:18.163 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.163 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.163 return
2025-07-02 06:41:18.163 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.163 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.163 else:
2025-07-02 06:41:18.163 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.163 eqi = None
2025-07-02 06:41:18.163
2025-07-02 06:41:18.163 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.163 # identical
2025-07-02 06:41:18.163
2025-07-02 06:41:18.163 # pump out diffs from before the synch point
2025-07-02 06:41:18.163 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.163
2025-07-02 06:41:18.163 # do intraline marking on the synch pair
2025-07-02 06:41:18.163 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.163 if eqi is None:
2025-07-02 06:41:18.163 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.164 atags = btags = ""
2025-07-02 06:41:18.164 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.164 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.164 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.164 if tag == 'replace':
2025-07-02 06:41:18.164 atags += '^' * la
2025-07-02 06:41:18.164 btags += '^' * lb
2025-07-02 06:41:18.164 elif tag == 'delete':
2025-07-02 06:41:18.164 atags += '-' * la
2025-07-02 06:41:18.164 elif tag == 'insert':
2025-07-02 06:41:18.164 btags += '+' * lb
2025-07-02 06:41:18.164 elif tag == 'equal':
2025-07-02 06:41:18.164 atags += ' ' * la
2025-07-02 06:41:18.164 btags += ' ' * lb
2025-07-02 06:41:18.164 else:
2025-07-02 06:41:18.164 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.164 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.164 else:
2025-07-02 06:41:18.164 # the synch pair is identical
2025-07-02 06:41:18.164 yield ' ' + aelt
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165 # pump out diffs from after the synch point
2025-07-02 06:41:18.165 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.165 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.165 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.165 alo = 353, ahi = 1101
2025-07-02 06:41:18.165 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.165 blo = 353, bhi = 1101
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.165 g = []
2025-07-02 06:41:18.165 if alo < ahi:
2025-07-02 06:41:18.165 if blo < bhi:
2025-07-02 06:41:18.165 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.165 else:
2025-07-02 06:41:18.166 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.166 elif blo < bhi:
2025-07-02 06:41:18.166 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 > yield from g
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.166 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.166 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.166 alo = 353, ahi = 1101
2025-07-02 06:41:18.166 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.166 blo = 353, bhi = 1101
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.166 r"""
2025-07-02 06:41:18.166 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.166 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.167 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.167 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.167
2025-07-02 06:41:18.167 Example:
2025-07-02 06:41:18.167
2025-07-02 06:41:18.167 >>> d = Differ()
2025-07-02 06:41:18.167 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.167 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.167 >>> print(''.join(results), end="")
2025-07-02 06:41:18.167 - abcDefghiJkl
2025-07-02 06:41:18.167 + abcdefGhijkl
2025-07-02 06:41:18.167 """
2025-07-02 06:41:18.167
2025-07-02 06:41:18.167 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.167 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.167 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.167 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.167 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.168
2025-07-02 06:41:18.168 # search for the pair that matches best without being identical
2025-07-02 06:41:18.168 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.168 # on junk -- unless we have to)
2025-07-02 06:41:18.168 for j in range(blo, bhi):
2025-07-02 06:41:18.168 bj = b[j]
2025-07-02 06:41:18.168 cruncher.set_seq2(bj)
2025-07-02 06:41:18.168 for i in range(alo, ahi):
2025-07-02 06:41:18.168 ai = a[i]
2025-07-02 06:41:18.168 if ai == bj:
2025-07-02 06:41:18.168 if eqi is None:
2025-07-02 06:41:18.168 eqi, eqj = i, j
2025-07-02 06:41:18.168 continue
2025-07-02 06:41:18.168 cruncher.set_seq1(ai)
2025-07-02 06:41:18.168 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.168 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.168 # compares by a factor of 3.
2025-07-02 06:41:18.169 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.169 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.169 # of the computation is cached by cruncher
2025-07-02 06:41:18.169 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.169 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.169 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.169 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.169 if best_ratio < cutoff:
2025-07-02 06:41:18.169 # no non-identical "pretty close" pair
2025-07-02 06:41:18.169 if eqi is None:
2025-07-02 06:41:18.169 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.169 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.169 return
2025-07-02 06:41:18.169 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.169 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.169 else:
2025-07-02 06:41:18.169 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.169 eqi = None
2025-07-02 06:41:18.169
2025-07-02 06:41:18.170 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.170 # identical
2025-07-02 06:41:18.170
2025-07-02 06:41:18.170 # pump out diffs from before the synch point
2025-07-02 06:41:18.170 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.170
2025-07-02 06:41:18.170 # do intraline marking on the synch pair
2025-07-02 06:41:18.170 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.170 if eqi is None:
2025-07-02 06:41:18.170 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.170 atags = btags = ""
2025-07-02 06:41:18.170 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.170 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.170 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.170 if tag == 'replace':
2025-07-02 06:41:18.170 atags += '^' * la
2025-07-02 06:41:18.170 btags += '^' * lb
2025-07-02 06:41:18.170 elif tag == 'delete':
2025-07-02 06:41:18.170 atags += '-' * la
2025-07-02 06:41:18.171 elif tag == 'insert':
2025-07-02 06:41:18.171 btags += '+' * lb
2025-07-02 06:41:18.171 elif tag == 'equal':
2025-07-02 06:41:18.171 atags += ' ' * la
2025-07-02 06:41:18.171 btags += ' ' * lb
2025-07-02 06:41:18.171 else:
2025-07-02 06:41:18.171 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.171 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.171 else:
2025-07-02 06:41:18.171 # the synch pair is identical
2025-07-02 06:41:18.171 yield ' ' + aelt
2025-07-02 06:41:18.171
2025-07-02 06:41:18.171 # pump out diffs from after the synch point
2025-07-02 06:41:18.171 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.171
2025-07-02 06:41:18.171 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.171 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.171
2025-07-02 06:41:18.171 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.172 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.172 alo = 356, ahi = 1101
2025-07-02 06:41:18.172 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.172 blo = 356, bhi = 1101
2025-07-02 06:41:18.172
2025-07-02 06:41:18.172 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.172 g = []
2025-07-02 06:41:18.172 if alo < ahi:
2025-07-02 06:41:18.172 if blo < bhi:
2025-07-02 06:41:18.172 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.172 else:
2025-07-02 06:41:18.172 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.172 elif blo < bhi:
2025-07-02 06:41:18.172 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.172
2025-07-02 06:41:18.172 > yield from g
2025-07-02 06:41:18.172
2025-07-02 06:41:18.172 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.172 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.173 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.173 alo = 356, ahi = 1101
2025-07-02 06:41:18.173 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.173 blo = 356, bhi = 1101
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.173 r"""
2025-07-02 06:41:18.173 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.173 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.173 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.173 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173 Example:
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173 >>> d = Differ()
2025-07-02 06:41:18.173 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.173 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.174 >>> print(''.join(results), end="")
2025-07-02 06:41:18.174 - abcDefghiJkl
2025-07-02 06:41:18.174 + abcdefGhijkl
2025-07-02 06:41:18.174 """
2025-07-02 06:41:18.174
2025-07-02 06:41:18.174 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.174 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.174 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.174 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.174 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.174
2025-07-02 06:41:18.174 # search for the pair that matches best without being identical
2025-07-02 06:41:18.174 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.174 # on junk -- unless we have to)
2025-07-02 06:41:18.174 for j in range(blo, bhi):
2025-07-02 06:41:18.174 bj = b[j]
2025-07-02 06:41:18.174 cruncher.set_seq2(bj)
2025-07-02 06:41:18.175 for i in range(alo, ahi):
2025-07-02 06:41:18.175 ai = a[i]
2025-07-02 06:41:18.175 if ai == bj:
2025-07-02 06:41:18.175 if eqi is None:
2025-07-02 06:41:18.175 eqi, eqj = i, j
2025-07-02 06:41:18.175 continue
2025-07-02 06:41:18.175 cruncher.set_seq1(ai)
2025-07-02 06:41:18.175 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.175 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.175 # compares by a factor of 3.
2025-07-02 06:41:18.175 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.175 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.175 # of the computation is cached by cruncher
2025-07-02 06:41:18.175 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.175 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.175 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.175 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.175 if best_ratio < cutoff:
2025-07-02 06:41:18.175 # no non-identical "pretty close" pair
2025-07-02 06:41:18.175 if eqi is None:
2025-07-02 06:41:18.176 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.176 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.176 return
2025-07-02 06:41:18.176 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.176 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.176 else:
2025-07-02 06:41:18.176 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.176 eqi = None
2025-07-02 06:41:18.176
2025-07-02 06:41:18.176 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.176 # identical
2025-07-02 06:41:18.176
2025-07-02 06:41:18.176 # pump out diffs from before the synch point
2025-07-02 06:41:18.176 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.176
2025-07-02 06:41:18.176 # do intraline marking on the synch pair
2025-07-02 06:41:18.176 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.176 if eqi is None:
2025-07-02 06:41:18.176 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.177 atags = btags = ""
2025-07-02 06:41:18.177 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.177 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.177 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.177 if tag == 'replace':
2025-07-02 06:41:18.177 atags += '^' * la
2025-07-02 06:41:18.177 btags += '^' * lb
2025-07-02 06:41:18.177 elif tag == 'delete':
2025-07-02 06:41:18.177 atags += '-' * la
2025-07-02 06:41:18.177 elif tag == 'insert':
2025-07-02 06:41:18.177 btags += '+' * lb
2025-07-02 06:41:18.177 elif tag == 'equal':
2025-07-02 06:41:18.177 atags += ' ' * la
2025-07-02 06:41:18.177 btags += ' ' * lb
2025-07-02 06:41:18.177 else:
2025-07-02 06:41:18.177 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.177 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.177 else:
2025-07-02 06:41:18.177 # the synch pair is identical
2025-07-02 06:41:18.178 yield ' ' + aelt
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178 # pump out diffs from after the synch point
2025-07-02 06:41:18.178 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.178 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.178 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.178 alo = 357, ahi = 1101
2025-07-02 06:41:18.178 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.178 blo = 357, bhi = 1101
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.178 g = []
2025-07-02 06:41:18.178 if alo < ahi:
2025-07-02 06:41:18.178 if blo < bhi:
2025-07-02 06:41:18.178 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.178 else:
2025-07-02 06:41:18.179 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.179 elif blo < bhi:
2025-07-02 06:41:18.179 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 > yield from g
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.179 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.179 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.179 alo = 357, ahi = 1101
2025-07-02 06:41:18.179 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.179 blo = 357, bhi = 1101
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.179 r"""
2025-07-02 06:41:18.179 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.180 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.180 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.180 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.180
2025-07-02 06:41:18.180 Example:
2025-07-02 06:41:18.180
2025-07-02 06:41:18.180 >>> d = Differ()
2025-07-02 06:41:18.180 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.180 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.180 >>> print(''.join(results), end="")
2025-07-02 06:41:18.180 - abcDefghiJkl
2025-07-02 06:41:18.180 + abcdefGhijkl
2025-07-02 06:41:18.180 """
2025-07-02 06:41:18.180
2025-07-02 06:41:18.180 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.180 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.180 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.180 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.181 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.181
2025-07-02 06:41:18.181 # search for the pair that matches best without being identical
2025-07-02 06:41:18.181 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.181 # on junk -- unless we have to)
2025-07-02 06:41:18.181 for j in range(blo, bhi):
2025-07-02 06:41:18.181 bj = b[j]
2025-07-02 06:41:18.181 cruncher.set_seq2(bj)
2025-07-02 06:41:18.181 for i in range(alo, ahi):
2025-07-02 06:41:18.181 ai = a[i]
2025-07-02 06:41:18.181 if ai == bj:
2025-07-02 06:41:18.181 if eqi is None:
2025-07-02 06:41:18.181 eqi, eqj = i, j
2025-07-02 06:41:18.181 continue
2025-07-02 06:41:18.181 cruncher.set_seq1(ai)
2025-07-02 06:41:18.181 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.181 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.181 # compares by a factor of 3.
2025-07-02 06:41:18.181 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.182 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.182 # of the computation is cached by cruncher
2025-07-02 06:41:18.182 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.182 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.182 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.182 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.182 if best_ratio < cutoff:
2025-07-02 06:41:18.182 # no non-identical "pretty close" pair
2025-07-02 06:41:18.182 if eqi is None:
2025-07-02 06:41:18.182 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.182 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.182 return
2025-07-02 06:41:18.182 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.182 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.182 else:
2025-07-02 06:41:18.182 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.182 eqi = None
2025-07-02 06:41:18.182
2025-07-02 06:41:18.182 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.182 # identical
2025-07-02 06:41:18.183
2025-07-02 06:41:18.183 # pump out diffs from before the synch point
2025-07-02 06:41:18.183 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.183
2025-07-02 06:41:18.183 # do intraline marking on the synch pair
2025-07-02 06:41:18.183 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.183 if eqi is None:
2025-07-02 06:41:18.183 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.183 atags = btags = ""
2025-07-02 06:41:18.183 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.183 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.183 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.183 if tag == 'replace':
2025-07-02 06:41:18.183 atags += '^' * la
2025-07-02 06:41:18.183 btags += '^' * lb
2025-07-02 06:41:18.183 elif tag == 'delete':
2025-07-02 06:41:18.183 atags += '-' * la
2025-07-02 06:41:18.183 elif tag == 'insert':
2025-07-02 06:41:18.184 btags += '+' * lb
2025-07-02 06:41:18.184 elif tag == 'equal':
2025-07-02 06:41:18.184 atags += ' ' * la
2025-07-02 06:41:18.184 btags += ' ' * lb
2025-07-02 06:41:18.184 else:
2025-07-02 06:41:18.184 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.184 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.184 else:
2025-07-02 06:41:18.184 # the synch pair is identical
2025-07-02 06:41:18.184 yield ' ' + aelt
2025-07-02 06:41:18.184
2025-07-02 06:41:18.184 # pump out diffs from after the synch point
2025-07-02 06:41:18.184 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.184
2025-07-02 06:41:18.184 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.184 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.184
2025-07-02 06:41:18.184 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.184 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.184 alo = 358, ahi = 1101
2025-07-02 06:41:18.185 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.185 blo = 358, bhi = 1101
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.185 g = []
2025-07-02 06:41:18.185 if alo < ahi:
2025-07-02 06:41:18.185 if blo < bhi:
2025-07-02 06:41:18.185 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.185 else:
2025-07-02 06:41:18.185 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.185 elif blo < bhi:
2025-07-02 06:41:18.185 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 > yield from g
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.185 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.185 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.186 alo = 358, ahi = 1101
2025-07-02 06:41:18.186 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.186 blo = 358, bhi = 1101
2025-07-02 06:41:18.186
2025-07-02 06:41:18.186 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.186 r"""
2025-07-02 06:41:18.186 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.186 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.186 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.186 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.186
2025-07-02 06:41:18.186 Example:
2025-07-02 06:41:18.186
2025-07-02 06:41:18.186 >>> d = Differ()
2025-07-02 06:41:18.186 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.186 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.186 >>> print(''.join(results), end="")
2025-07-02 06:41:18.186 - abcDefghiJkl
2025-07-02 06:41:18.186 + abcdefGhijkl
2025-07-02 06:41:18.187 """
2025-07-02 06:41:18.187
2025-07-02 06:41:18.187 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.187 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.187 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.187 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.187 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.187
2025-07-02 06:41:18.187 # search for the pair that matches best without being identical
2025-07-02 06:41:18.187 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.187 # on junk -- unless we have to)
2025-07-02 06:41:18.187 for j in range(blo, bhi):
2025-07-02 06:41:18.187 bj = b[j]
2025-07-02 06:41:18.187 cruncher.set_seq2(bj)
2025-07-02 06:41:18.187 for i in range(alo, ahi):
2025-07-02 06:41:18.187 ai = a[i]
2025-07-02 06:41:18.187 if ai == bj:
2025-07-02 06:41:18.187 if eqi is None:
2025-07-02 06:41:18.187 eqi, eqj = i, j
2025-07-02 06:41:18.187 continue
2025-07-02 06:41:18.188 cruncher.set_seq1(ai)
2025-07-02 06:41:18.188 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.188 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.188 # compares by a factor of 3.
2025-07-02 06:41:18.188 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.188 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.188 # of the computation is cached by cruncher
2025-07-02 06:41:18.188 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.188 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.188 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.188 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.188 if best_ratio < cutoff:
2025-07-02 06:41:18.188 # no non-identical "pretty close" pair
2025-07-02 06:41:18.188 if eqi is None:
2025-07-02 06:41:18.188 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.188 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.188 return
2025-07-02 06:41:18.188 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.189 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.189 else:
2025-07-02 06:41:18.189 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.189 eqi = None
2025-07-02 06:41:18.189
2025-07-02 06:41:18.189 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.189 # identical
2025-07-02 06:41:18.189
2025-07-02 06:41:18.189 # pump out diffs from before the synch point
2025-07-02 06:41:18.189 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.189
2025-07-02 06:41:18.189 # do intraline marking on the synch pair
2025-07-02 06:41:18.189 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.189 if eqi is None:
2025-07-02 06:41:18.189 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.189 atags = btags = ""
2025-07-02 06:41:18.189 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.189 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.189 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.190 if tag == 'replace':
2025-07-02 06:41:18.190 atags += '^' * la
2025-07-02 06:41:18.190 btags += '^' * lb
2025-07-02 06:41:18.190 elif tag == 'delete':
2025-07-02 06:41:18.190 atags += '-' * la
2025-07-02 06:41:18.190 elif tag == 'insert':
2025-07-02 06:41:18.190 btags += '+' * lb
2025-07-02 06:41:18.190 elif tag == 'equal':
2025-07-02 06:41:18.190 atags += ' ' * la
2025-07-02 06:41:18.190 btags += ' ' * lb
2025-07-02 06:41:18.190 else:
2025-07-02 06:41:18.190 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.190 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.190 else:
2025-07-02 06:41:18.190 # the synch pair is identical
2025-07-02 06:41:18.190 yield ' ' + aelt
2025-07-02 06:41:18.190
2025-07-02 06:41:18.190 # pump out diffs from after the synch point
2025-07-02 06:41:18.190 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.190
2025-07-02 06:41:18.191 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.191 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.191
2025-07-02 06:41:18.191 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.191 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.191 alo = 359, ahi = 1101
2025-07-02 06:41:18.191 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.191 blo = 359, bhi = 1101
2025-07-02 06:41:18.191
2025-07-02 06:41:18.191 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.191 g = []
2025-07-02 06:41:18.191 if alo < ahi:
2025-07-02 06:41:18.191 if blo < bhi:
2025-07-02 06:41:18.191 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.191 else:
2025-07-02 06:41:18.191 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.191 elif blo < bhi:
2025-07-02 06:41:18.191 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.191
2025-07-02 06:41:18.191 > yield from g
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.192 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.192 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.192 alo = 359, ahi = 1101
2025-07-02 06:41:18.192 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.192 blo = 359, bhi = 1101
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.192 r"""
2025-07-02 06:41:18.192 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.192 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.192 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.192 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 Example:
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 >>> d = Differ()
2025-07-02 06:41:18.192 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.193 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.193 >>> print(''.join(results), end="")
2025-07-02 06:41:18.193 - abcDefghiJkl
2025-07-02 06:41:18.193 + abcdefGhijkl
2025-07-02 06:41:18.193 """
2025-07-02 06:41:18.193
2025-07-02 06:41:18.193 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.193 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.193 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.193 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.193 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.193
2025-07-02 06:41:18.193 # search for the pair that matches best without being identical
2025-07-02 06:41:18.193 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.193 # on junk -- unless we have to)
2025-07-02 06:41:18.193 for j in range(blo, bhi):
2025-07-02 06:41:18.193 bj = b[j]
2025-07-02 06:41:18.193 cruncher.set_seq2(bj)
2025-07-02 06:41:18.194 for i in range(alo, ahi):
2025-07-02 06:41:18.194 ai = a[i]
2025-07-02 06:41:18.194 if ai == bj:
2025-07-02 06:41:18.194 if eqi is None:
2025-07-02 06:41:18.194 eqi, eqj = i, j
2025-07-02 06:41:18.194 continue
2025-07-02 06:41:18.194 cruncher.set_seq1(ai)
2025-07-02 06:41:18.194 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.194 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.194 # compares by a factor of 3.
2025-07-02 06:41:18.194 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.194 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.194 # of the computation is cached by cruncher
2025-07-02 06:41:18.194 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.194 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.194 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.194 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.194 if best_ratio < cutoff:
2025-07-02 06:41:18.194 # no non-identical "pretty close" pair
2025-07-02 06:41:18.194 if eqi is None:
2025-07-02 06:41:18.195 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.195 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.195 return
2025-07-02 06:41:18.195 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.195 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.195 else:
2025-07-02 06:41:18.195 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.195 eqi = None
2025-07-02 06:41:18.195
2025-07-02 06:41:18.195 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.195 # identical
2025-07-02 06:41:18.195
2025-07-02 06:41:18.195 # pump out diffs from before the synch point
2025-07-02 06:41:18.195 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.195
2025-07-02 06:41:18.195 # do intraline marking on the synch pair
2025-07-02 06:41:18.195 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.195 if eqi is None:
2025-07-02 06:41:18.195 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.195 atags = btags = ""
2025-07-02 06:41:18.196 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.196 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.196 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.196 if tag == 'replace':
2025-07-02 06:41:18.196 atags += '^' * la
2025-07-02 06:41:18.196 btags += '^' * lb
2025-07-02 06:41:18.196 elif tag == 'delete':
2025-07-02 06:41:18.196 atags += '-' * la
2025-07-02 06:41:18.196 elif tag == 'insert':
2025-07-02 06:41:18.196 btags += '+' * lb
2025-07-02 06:41:18.196 elif tag == 'equal':
2025-07-02 06:41:18.196 atags += ' ' * la
2025-07-02 06:41:18.196 btags += ' ' * lb
2025-07-02 06:41:18.196 else:
2025-07-02 06:41:18.196 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.196 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.196 else:
2025-07-02 06:41:18.196 # the synch pair is identical
2025-07-02 06:41:18.196 yield ' ' + aelt
2025-07-02 06:41:18.196
2025-07-02 06:41:18.196 # pump out diffs from after the synch point
2025-07-02 06:41:18.197 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.197
2025-07-02 06:41:18.197 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.197 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.197
2025-07-02 06:41:18.197 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.197 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.197 alo = 360, ahi = 1101
2025-07-02 06:41:18.197 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.197 blo = 360, bhi = 1101
2025-07-02 06:41:18.197
2025-07-02 06:41:18.197 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.197 g = []
2025-07-02 06:41:18.197 if alo < ahi:
2025-07-02 06:41:18.197 if blo < bhi:
2025-07-02 06:41:18.197 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.197 else:
2025-07-02 06:41:18.197 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.198 elif blo < bhi:
2025-07-02 06:41:18.198 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 > yield from g
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.198 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.198 alo = 360, ahi = 1101
2025-07-02 06:41:18.198 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.198 blo = 360, bhi = 1101
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.198 r"""
2025-07-02 06:41:18.198 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.198 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.198 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.199 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.199
2025-07-02 06:41:18.199 Example:
2025-07-02 06:41:18.199
2025-07-02 06:41:18.199 >>> d = Differ()
2025-07-02 06:41:18.199 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.199 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.199 >>> print(''.join(results), end="")
2025-07-02 06:41:18.199 - abcDefghiJkl
2025-07-02 06:41:18.199 + abcdefGhijkl
2025-07-02 06:41:18.199 """
2025-07-02 06:41:18.199
2025-07-02 06:41:18.199 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.199 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.199 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.199 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.199 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.200
2025-07-02 06:41:18.200 # search for the pair that matches best without being identical
2025-07-02 06:41:18.200 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.200 # on junk -- unless we have to)
2025-07-02 06:41:18.200 for j in range(blo, bhi):
2025-07-02 06:41:18.200 bj = b[j]
2025-07-02 06:41:18.200 cruncher.set_seq2(bj)
2025-07-02 06:41:18.200 for i in range(alo, ahi):
2025-07-02 06:41:18.200 ai = a[i]
2025-07-02 06:41:18.200 if ai == bj:
2025-07-02 06:41:18.200 if eqi is None:
2025-07-02 06:41:18.200 eqi, eqj = i, j
2025-07-02 06:41:18.200 continue
2025-07-02 06:41:18.200 cruncher.set_seq1(ai)
2025-07-02 06:41:18.200 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.200 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.200 # compares by a factor of 3.
2025-07-02 06:41:18.200 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.200 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.200 # of the computation is cached by cruncher
2025-07-02 06:41:18.201 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.201 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.201 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.201 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.201 if best_ratio < cutoff:
2025-07-02 06:41:18.201 # no non-identical "pretty close" pair
2025-07-02 06:41:18.201 if eqi is None:
2025-07-02 06:41:18.201 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.201 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.201 return
2025-07-02 06:41:18.201 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.201 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.201 else:
2025-07-02 06:41:18.201 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.201 eqi = None
2025-07-02 06:41:18.201
2025-07-02 06:41:18.201 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.201 # identical
2025-07-02 06:41:18.201
2025-07-02 06:41:18.201 # pump out diffs from before the synch point
2025-07-02 06:41:18.202 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.202
2025-07-02 06:41:18.202 # do intraline marking on the synch pair
2025-07-02 06:41:18.202 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.202 if eqi is None:
2025-07-02 06:41:18.202 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.202 atags = btags = ""
2025-07-02 06:41:18.202 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.202 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.202 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.202 if tag == 'replace':
2025-07-02 06:41:18.202 atags += '^' * la
2025-07-02 06:41:18.202 btags += '^' * lb
2025-07-02 06:41:18.202 elif tag == 'delete':
2025-07-02 06:41:18.202 atags += '-' * la
2025-07-02 06:41:18.202 elif tag == 'insert':
2025-07-02 06:41:18.202 btags += '+' * lb
2025-07-02 06:41:18.202 elif tag == 'equal':
2025-07-02 06:41:18.202 atags += ' ' * la
2025-07-02 06:41:18.202 btags += ' ' * lb
2025-07-02 06:41:18.203 else:
2025-07-02 06:41:18.203 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.203 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.203 else:
2025-07-02 06:41:18.203 # the synch pair is identical
2025-07-02 06:41:18.203 yield ' ' + aelt
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203 # pump out diffs from after the synch point
2025-07-02 06:41:18.203 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.203 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.203 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.203 alo = 361, ahi = 1101
2025-07-02 06:41:18.203 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.203 blo = 361, bhi = 1101
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.204 g = []
2025-07-02 06:41:18.204 if alo < ahi:
2025-07-02 06:41:18.204 if blo < bhi:
2025-07-02 06:41:18.204 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.204 else:
2025-07-02 06:41:18.204 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.204 elif blo < bhi:
2025-07-02 06:41:18.204 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.204
2025-07-02 06:41:18.204 > yield from g
2025-07-02 06:41:18.204
2025-07-02 06:41:18.204 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.204 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.204
2025-07-02 06:41:18.204 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.204 alo = 361, ahi = 1101
2025-07-02 06:41:18.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.204 blo = 361, bhi = 1101
2025-07-02 06:41:18.204
2025-07-02 06:41:18.205 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.205 r"""
2025-07-02 06:41:18.205 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.205 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.205 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.205 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.205
2025-07-02 06:41:18.205 Example:
2025-07-02 06:41:18.205
2025-07-02 06:41:18.205 >>> d = Differ()
2025-07-02 06:41:18.205 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.205 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.205 >>> print(''.join(results), end="")
2025-07-02 06:41:18.205 - abcDefghiJkl
2025-07-02 06:41:18.205 + abcdefGhijkl
2025-07-02 06:41:18.205 """
2025-07-02 06:41:18.205
2025-07-02 06:41:18.205 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.205 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.206 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.206 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.206 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.206
2025-07-02 06:41:18.206 # search for the pair that matches best without being identical
2025-07-02 06:41:18.206 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.206 # on junk -- unless we have to)
2025-07-02 06:41:18.206 for j in range(blo, bhi):
2025-07-02 06:41:18.206 bj = b[j]
2025-07-02 06:41:18.206 cruncher.set_seq2(bj)
2025-07-02 06:41:18.206 for i in range(alo, ahi):
2025-07-02 06:41:18.206 ai = a[i]
2025-07-02 06:41:18.206 if ai == bj:
2025-07-02 06:41:18.206 if eqi is None:
2025-07-02 06:41:18.206 eqi, eqj = i, j
2025-07-02 06:41:18.206 continue
2025-07-02 06:41:18.206 cruncher.set_seq1(ai)
2025-07-02 06:41:18.207 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.207 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.207 # compares by a factor of 3.
2025-07-02 06:41:18.207 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.207 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.207 # of the computation is cached by cruncher
2025-07-02 06:41:18.207 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.207 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.207 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.207 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.207 if best_ratio < cutoff:
2025-07-02 06:41:18.207 # no non-identical "pretty close" pair
2025-07-02 06:41:18.207 if eqi is None:
2025-07-02 06:41:18.207 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.207 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.207 return
2025-07-02 06:41:18.207 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.207 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.207 else:
2025-07-02 06:41:18.207 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.208 eqi = None
2025-07-02 06:41:18.208
2025-07-02 06:41:18.208 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.208 # identical
2025-07-02 06:41:18.208
2025-07-02 06:41:18.208 # pump out diffs from before the synch point
2025-07-02 06:41:18.208 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.208
2025-07-02 06:41:18.208 # do intraline marking on the synch pair
2025-07-02 06:41:18.208 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.208 if eqi is None:
2025-07-02 06:41:18.208 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.208 atags = btags = ""
2025-07-02 06:41:18.208 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.208 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.208 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.208 if tag == 'replace':
2025-07-02 06:41:18.208 atags += '^' * la
2025-07-02 06:41:18.208 btags += '^' * lb
2025-07-02 06:41:18.209 elif tag == 'delete':
2025-07-02 06:41:18.209 atags += '-' * la
2025-07-02 06:41:18.209 elif tag == 'insert':
2025-07-02 06:41:18.209 btags += '+' * lb
2025-07-02 06:41:18.209 elif tag == 'equal':
2025-07-02 06:41:18.209 atags += ' ' * la
2025-07-02 06:41:18.209 btags += ' ' * lb
2025-07-02 06:41:18.209 else:
2025-07-02 06:41:18.209 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.209 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.209 else:
2025-07-02 06:41:18.209 # the synch pair is identical
2025-07-02 06:41:18.209 yield ' ' + aelt
2025-07-02 06:41:18.209
2025-07-02 06:41:18.209 # pump out diffs from after the synch point
2025-07-02 06:41:18.209 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.209
2025-07-02 06:41:18.209 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.209 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.209
2025-07-02 06:41:18.210 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.210 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.210 alo = 362, ahi = 1101
2025-07-02 06:41:18.210 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.210 blo = 362, bhi = 1101
2025-07-02 06:41:18.210
2025-07-02 06:41:18.210 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.210 g = []
2025-07-02 06:41:18.210 if alo < ahi:
2025-07-02 06:41:18.210 if blo < bhi:
2025-07-02 06:41:18.210 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.210 else:
2025-07-02 06:41:18.210 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.210 elif blo < bhi:
2025-07-02 06:41:18.210 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.210
2025-07-02 06:41:18.210 > yield from g
2025-07-02 06:41:18.210
2025-07-02 06:41:18.210 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.211 alo = 362, ahi = 1101
2025-07-02 06:41:18.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.211 blo = 362, bhi = 1101
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.211 r"""
2025-07-02 06:41:18.211 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.211 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.211 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.211 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211 Example:
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211 >>> d = Differ()
2025-07-02 06:41:18.211 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.212 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.212 >>> print(''.join(results), end="")
2025-07-02 06:41:18.212 - abcDefghiJkl
2025-07-02 06:41:18.212 + abcdefGhijkl
2025-07-02 06:41:18.212 """
2025-07-02 06:41:18.212
2025-07-02 06:41:18.212 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.212 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.212 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.212 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.212 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.212
2025-07-02 06:41:18.212 # search for the pair that matches best without being identical
2025-07-02 06:41:18.212 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.212 # on junk -- unless we have to)
2025-07-02 06:41:18.212 for j in range(blo, bhi):
2025-07-02 06:41:18.212 bj = b[j]
2025-07-02 06:41:18.212 cruncher.set_seq2(bj)
2025-07-02 06:41:18.213 for i in range(alo, ahi):
2025-07-02 06:41:18.213 ai = a[i]
2025-07-02 06:41:18.213 if ai == bj:
2025-07-02 06:41:18.213 if eqi is None:
2025-07-02 06:41:18.213 eqi, eqj = i, j
2025-07-02 06:41:18.213 continue
2025-07-02 06:41:18.213 cruncher.set_seq1(ai)
2025-07-02 06:41:18.213 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.213 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.213 # compares by a factor of 3.
2025-07-02 06:41:18.213 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.213 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.213 # of the computation is cached by cruncher
2025-07-02 06:41:18.213 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.213 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.213 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.213 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.213 if best_ratio < cutoff:
2025-07-02 06:41:18.213 # no non-identical "pretty close" pair
2025-07-02 06:41:18.213 if eqi is None:
2025-07-02 06:41:18.214 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.214 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.214 return
2025-07-02 06:41:18.214 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.214 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.214 else:
2025-07-02 06:41:18.214 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.214 eqi = None
2025-07-02 06:41:18.214
2025-07-02 06:41:18.214 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.214 # identical
2025-07-02 06:41:18.214
2025-07-02 06:41:18.214 # pump out diffs from before the synch point
2025-07-02 06:41:18.214 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.214
2025-07-02 06:41:18.214 # do intraline marking on the synch pair
2025-07-02 06:41:18.214 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.214 if eqi is None:
2025-07-02 06:41:18.214 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.215 atags = btags = ""
2025-07-02 06:41:18.215 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.215 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.215 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.215 if tag == 'replace':
2025-07-02 06:41:18.215 atags += '^' * la
2025-07-02 06:41:18.215 btags += '^' * lb
2025-07-02 06:41:18.215 elif tag == 'delete':
2025-07-02 06:41:18.215 atags += '-' * la
2025-07-02 06:41:18.215 elif tag == 'insert':
2025-07-02 06:41:18.215 btags += '+' * lb
2025-07-02 06:41:18.215 elif tag == 'equal':
2025-07-02 06:41:18.215 atags += ' ' * la
2025-07-02 06:41:18.215 btags += ' ' * lb
2025-07-02 06:41:18.215 else:
2025-07-02 06:41:18.215 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.215 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.216 else:
2025-07-02 06:41:18.216 # the synch pair is identical
2025-07-02 06:41:18.216 yield ' ' + aelt
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216 # pump out diffs from after the synch point
2025-07-02 06:41:18.216 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.216 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.216 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.216 alo = 363, ahi = 1101
2025-07-02 06:41:18.216 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.216 blo = 363, bhi = 1101
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.216 g = []
2025-07-02 06:41:18.216 if alo < ahi:
2025-07-02 06:41:18.217 if blo < bhi:
2025-07-02 06:41:18.217 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.217 else:
2025-07-02 06:41:18.217 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.217 elif blo < bhi:
2025-07-02 06:41:18.217 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 > yield from g
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.217 alo = 363, ahi = 1101
2025-07-02 06:41:18.217 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.217 blo = 363, bhi = 1101
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.218 r"""
2025-07-02 06:41:18.218 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.218 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.218 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.218 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.218
2025-07-02 06:41:18.218 Example:
2025-07-02 06:41:18.218
2025-07-02 06:41:18.218 >>> d = Differ()
2025-07-02 06:41:18.218 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.218 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.218 >>> print(''.join(results), end="")
2025-07-02 06:41:18.218 - abcDefghiJkl
2025-07-02 06:41:18.218 + abcdefGhijkl
2025-07-02 06:41:18.218 """
2025-07-02 06:41:18.218
2025-07-02 06:41:18.218 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.218 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.219 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.219 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.219 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.219
2025-07-02 06:41:18.219 # search for the pair that matches best without being identical
2025-07-02 06:41:18.219 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.219 # on junk -- unless we have to)
2025-07-02 06:41:18.219 for j in range(blo, bhi):
2025-07-02 06:41:18.219 bj = b[j]
2025-07-02 06:41:18.219 cruncher.set_seq2(bj)
2025-07-02 06:41:18.219 for i in range(alo, ahi):
2025-07-02 06:41:18.219 ai = a[i]
2025-07-02 06:41:18.219 if ai == bj:
2025-07-02 06:41:18.219 if eqi is None:
2025-07-02 06:41:18.219 eqi, eqj = i, j
2025-07-02 06:41:18.219 continue
2025-07-02 06:41:18.219 cruncher.set_seq1(ai)
2025-07-02 06:41:18.219 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.219 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.220 # compares by a factor of 3.
2025-07-02 06:41:18.220 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.220 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.220 # of the computation is cached by cruncher
2025-07-02 06:41:18.220 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.220 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.220 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.220 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.220 if best_ratio < cutoff:
2025-07-02 06:41:18.220 # no non-identical "pretty close" pair
2025-07-02 06:41:18.220 if eqi is None:
2025-07-02 06:41:18.220 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.220 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.220 return
2025-07-02 06:41:18.220 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.220 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.220 else:
2025-07-02 06:41:18.220 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.220 eqi = None
2025-07-02 06:41:18.221
2025-07-02 06:41:18.221 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.221 # identical
2025-07-02 06:41:18.221
2025-07-02 06:41:18.221 # pump out diffs from before the synch point
2025-07-02 06:41:18.221 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.221
2025-07-02 06:41:18.221 # do intraline marking on the synch pair
2025-07-02 06:41:18.221 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.221 if eqi is None:
2025-07-02 06:41:18.221 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.221 atags = btags = ""
2025-07-02 06:41:18.221 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.221 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.221 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.221 if tag == 'replace':
2025-07-02 06:41:18.221 atags += '^' * la
2025-07-02 06:41:18.221 btags += '^' * lb
2025-07-02 06:41:18.221 elif tag == 'delete':
2025-07-02 06:41:18.221 atags += '-' * la
2025-07-02 06:41:18.222 elif tag == 'insert':
2025-07-02 06:41:18.222 btags += '+' * lb
2025-07-02 06:41:18.222 elif tag == 'equal':
2025-07-02 06:41:18.222 atags += ' ' * la
2025-07-02 06:41:18.222 btags += ' ' * lb
2025-07-02 06:41:18.222 else:
2025-07-02 06:41:18.222 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.222 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.222 else:
2025-07-02 06:41:18.222 # the synch pair is identical
2025-07-02 06:41:18.222 yield ' ' + aelt
2025-07-02 06:41:18.222
2025-07-02 06:41:18.222 # pump out diffs from after the synch point
2025-07-02 06:41:18.222 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.222
2025-07-02 06:41:18.222 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.222 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.222
2025-07-02 06:41:18.222 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.223 alo = 364, ahi = 1101
2025-07-02 06:41:18.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.223 blo = 364, bhi = 1101
2025-07-02 06:41:18.223
2025-07-02 06:41:18.223 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.223 g = []
2025-07-02 06:41:18.223 if alo < ahi:
2025-07-02 06:41:18.223 if blo < bhi:
2025-07-02 06:41:18.223 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.223 else:
2025-07-02 06:41:18.223 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.223 elif blo < bhi:
2025-07-02 06:41:18.223 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.223
2025-07-02 06:41:18.223 > yield from g
2025-07-02 06:41:18.223
2025-07-02 06:41:18.223 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.224 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.224 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.224 alo = 364, ahi = 1101
2025-07-02 06:41:18.224 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.224 blo = 364, bhi = 1101
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.224 r"""
2025-07-02 06:41:18.224 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.224 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.224 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.224 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224 Example:
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224 >>> d = Differ()
2025-07-02 06:41:18.224 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.225 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.225 >>> print(''.join(results), end="")
2025-07-02 06:41:18.225 - abcDefghiJkl
2025-07-02 06:41:18.225 + abcdefGhijkl
2025-07-02 06:41:18.225 """
2025-07-02 06:41:18.225
2025-07-02 06:41:18.225 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.225 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.225 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.225 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.225 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.225
2025-07-02 06:41:18.225 # search for the pair that matches best without being identical
2025-07-02 06:41:18.225 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.225 # on junk -- unless we have to)
2025-07-02 06:41:18.225 for j in range(blo, bhi):
2025-07-02 06:41:18.225 bj = b[j]
2025-07-02 06:41:18.225 cruncher.set_seq2(bj)
2025-07-02 06:41:18.226 for i in range(alo, ahi):
2025-07-02 06:41:18.226 ai = a[i]
2025-07-02 06:41:18.226 if ai == bj:
2025-07-02 06:41:18.226 if eqi is None:
2025-07-02 06:41:18.226 eqi, eqj = i, j
2025-07-02 06:41:18.226 continue
2025-07-02 06:41:18.226 cruncher.set_seq1(ai)
2025-07-02 06:41:18.226 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.226 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.226 # compares by a factor of 3.
2025-07-02 06:41:18.226 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.226 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.226 # of the computation is cached by cruncher
2025-07-02 06:41:18.226 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.226 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.226 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.226 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.226 if best_ratio < cutoff:
2025-07-02 06:41:18.226 # no non-identical "pretty close" pair
2025-07-02 06:41:18.227 if eqi is None:
2025-07-02 06:41:18.227 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.227 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.227 return
2025-07-02 06:41:18.227 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.227 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.227 else:
2025-07-02 06:41:18.227 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.227 eqi = None
2025-07-02 06:41:18.227
2025-07-02 06:41:18.227 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.227 # identical
2025-07-02 06:41:18.227
2025-07-02 06:41:18.227 # pump out diffs from before the synch point
2025-07-02 06:41:18.227 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.227
2025-07-02 06:41:18.227 # do intraline marking on the synch pair
2025-07-02 06:41:18.227 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.227 if eqi is None:
2025-07-02 06:41:18.227 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.228 atags = btags = ""
2025-07-02 06:41:18.228 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.228 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.228 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.228 if tag == 'replace':
2025-07-02 06:41:18.228 atags += '^' * la
2025-07-02 06:41:18.228 btags += '^' * lb
2025-07-02 06:41:18.228 elif tag == 'delete':
2025-07-02 06:41:18.228 atags += '-' * la
2025-07-02 06:41:18.228 elif tag == 'insert':
2025-07-02 06:41:18.228 btags += '+' * lb
2025-07-02 06:41:18.228 elif tag == 'equal':
2025-07-02 06:41:18.228 atags += ' ' * la
2025-07-02 06:41:18.228 btags += ' ' * lb
2025-07-02 06:41:18.228 else:
2025-07-02 06:41:18.228 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.228 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.228 else:
2025-07-02 06:41:18.228 # the synch pair is identical
2025-07-02 06:41:18.229 yield ' ' + aelt
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229 # pump out diffs from after the synch point
2025-07-02 06:41:18.229 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.229 alo = 365, ahi = 1101
2025-07-02 06:41:18.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.229 blo = 365, bhi = 1101
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.229 g = []
2025-07-02 06:41:18.229 if alo < ahi:
2025-07-02 06:41:18.229 if blo < bhi:
2025-07-02 06:41:18.229 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.230 else:
2025-07-02 06:41:18.230 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.230 elif blo < bhi:
2025-07-02 06:41:18.230 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 > yield from g
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.230 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.230 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.230 alo = 365, ahi = 1101
2025-07-02 06:41:18.230 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.230 blo = 365, bhi = 1101
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.230 r"""
2025-07-02 06:41:18.230 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.231 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.231 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.231 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.231
2025-07-02 06:41:18.231 Example:
2025-07-02 06:41:18.231
2025-07-02 06:41:18.231 >>> d = Differ()
2025-07-02 06:41:18.231 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.231 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.231 >>> print(''.join(results), end="")
2025-07-02 06:41:18.231 - abcDefghiJkl
2025-07-02 06:41:18.231 + abcdefGhijkl
2025-07-02 06:41:18.231 """
2025-07-02 06:41:18.231
2025-07-02 06:41:18.231 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.231 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.231 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.231 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.232 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.232
2025-07-02 06:41:18.232 # search for the pair that matches best without being identical
2025-07-02 06:41:18.232 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.232 # on junk -- unless we have to)
2025-07-02 06:41:18.232 for j in range(blo, bhi):
2025-07-02 06:41:18.232 bj = b[j]
2025-07-02 06:41:18.232 cruncher.set_seq2(bj)
2025-07-02 06:41:18.232 for i in range(alo, ahi):
2025-07-02 06:41:18.232 ai = a[i]
2025-07-02 06:41:18.232 if ai == bj:
2025-07-02 06:41:18.232 if eqi is None:
2025-07-02 06:41:18.232 eqi, eqj = i, j
2025-07-02 06:41:18.232 continue
2025-07-02 06:41:18.232 cruncher.set_seq1(ai)
2025-07-02 06:41:18.232 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.232 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.232 # compares by a factor of 3.
2025-07-02 06:41:18.232 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.233 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.233 # of the computation is cached by cruncher
2025-07-02 06:41:18.233 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.233 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.233 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.233 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.233 if best_ratio < cutoff:
2025-07-02 06:41:18.233 # no non-identical "pretty close" pair
2025-07-02 06:41:18.233 if eqi is None:
2025-07-02 06:41:18.233 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.233 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.233 return
2025-07-02 06:41:18.233 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.233 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.233 else:
2025-07-02 06:41:18.233 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.233 eqi = None
2025-07-02 06:41:18.233
2025-07-02 06:41:18.234 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.234 # identical
2025-07-02 06:41:18.234
2025-07-02 06:41:18.234 # pump out diffs from before the synch point
2025-07-02 06:41:18.234 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.234
2025-07-02 06:41:18.234 # do intraline marking on the synch pair
2025-07-02 06:41:18.234 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.234 if eqi is None:
2025-07-02 06:41:18.234 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.234 atags = btags = ""
2025-07-02 06:41:18.234 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.234 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.234 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.234 if tag == 'replace':
2025-07-02 06:41:18.234 atags += '^' * la
2025-07-02 06:41:18.234 btags += '^' * lb
2025-07-02 06:41:18.234 elif tag == 'delete':
2025-07-02 06:41:18.234 atags += '-' * la
2025-07-02 06:41:18.234 elif tag == 'insert':
2025-07-02 06:41:18.235 btags += '+' * lb
2025-07-02 06:41:18.235 elif tag == 'equal':
2025-07-02 06:41:18.235 atags += ' ' * la
2025-07-02 06:41:18.235 btags += ' ' * lb
2025-07-02 06:41:18.235 else:
2025-07-02 06:41:18.235 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.235 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.235 else:
2025-07-02 06:41:18.235 # the synch pair is identical
2025-07-02 06:41:18.235 yield ' ' + aelt
2025-07-02 06:41:18.235
2025-07-02 06:41:18.235 # pump out diffs from after the synch point
2025-07-02 06:41:18.235 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.235
2025-07-02 06:41:18.235 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.235
2025-07-02 06:41:18.235 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.236 alo = 366, ahi = 1101
2025-07-02 06:41:18.236 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.236 blo = 366, bhi = 1101
2025-07-02 06:41:18.236
2025-07-02 06:41:18.236 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.236 g = []
2025-07-02 06:41:18.236 if alo < ahi:
2025-07-02 06:41:18.236 if blo < bhi:
2025-07-02 06:41:18.236 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.236 else:
2025-07-02 06:41:18.236 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.236 elif blo < bhi:
2025-07-02 06:41:18.236 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.236
2025-07-02 06:41:18.236 > yield from g
2025-07-02 06:41:18.236
2025-07-02 06:41:18.236 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.236 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.236
2025-07-02 06:41:18.237 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.237 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.237 alo = 366, ahi = 1101
2025-07-02 06:41:18.237 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.237 blo = 366, bhi = 1101
2025-07-02 06:41:18.237
2025-07-02 06:41:18.237 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.237 r"""
2025-07-02 06:41:18.237 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.237 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.237 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.237 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.237
2025-07-02 06:41:18.237 Example:
2025-07-02 06:41:18.237
2025-07-02 06:41:18.237 >>> d = Differ()
2025-07-02 06:41:18.237 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.237 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.237 >>> print(''.join(results), end="")
2025-07-02 06:41:18.237 - abcDefghiJkl
2025-07-02 06:41:18.238 + abcdefGhijkl
2025-07-02 06:41:18.238 """
2025-07-02 06:41:18.238
2025-07-02 06:41:18.238 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.238 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.238 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.238 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.238 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.238
2025-07-02 06:41:18.238 # search for the pair that matches best without being identical
2025-07-02 06:41:18.238 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.238 # on junk -- unless we have to)
2025-07-02 06:41:18.238 for j in range(blo, bhi):
2025-07-02 06:41:18.238 bj = b[j]
2025-07-02 06:41:18.238 cruncher.set_seq2(bj)
2025-07-02 06:41:18.238 for i in range(alo, ahi):
2025-07-02 06:41:18.238 ai = a[i]
2025-07-02 06:41:18.238 if ai == bj:
2025-07-02 06:41:18.238 if eqi is None:
2025-07-02 06:41:18.239 eqi, eqj = i, j
2025-07-02 06:41:18.239 continue
2025-07-02 06:41:18.239 cruncher.set_seq1(ai)
2025-07-02 06:41:18.239 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.239 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.239 # compares by a factor of 3.
2025-07-02 06:41:18.239 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.239 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.239 # of the computation is cached by cruncher
2025-07-02 06:41:18.239 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.239 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.239 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.239 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.239 if best_ratio < cutoff:
2025-07-02 06:41:18.239 # no non-identical "pretty close" pair
2025-07-02 06:41:18.239 if eqi is None:
2025-07-02 06:41:18.239 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.239 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.239 return
2025-07-02 06:41:18.239 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.240 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.240 else:
2025-07-02 06:41:18.240 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.240 eqi = None
2025-07-02 06:41:18.240
2025-07-02 06:41:18.240 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.240 # identical
2025-07-02 06:41:18.240
2025-07-02 06:41:18.240 # pump out diffs from before the synch point
2025-07-02 06:41:18.240 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.240
2025-07-02 06:41:18.240 # do intraline marking on the synch pair
2025-07-02 06:41:18.240 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.240 if eqi is None:
2025-07-02 06:41:18.240 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.240 atags = btags = ""
2025-07-02 06:41:18.240 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.240 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.240 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.240 if tag == 'replace':
2025-07-02 06:41:18.241 atags += '^' * la
2025-07-02 06:41:18.241 btags += '^' * lb
2025-07-02 06:41:18.241 elif tag == 'delete':
2025-07-02 06:41:18.241 atags += '-' * la
2025-07-02 06:41:18.241 elif tag == 'insert':
2025-07-02 06:41:18.241 btags += '+' * lb
2025-07-02 06:41:18.241 elif tag == 'equal':
2025-07-02 06:41:18.241 atags += ' ' * la
2025-07-02 06:41:18.241 btags += ' ' * lb
2025-07-02 06:41:18.241 else:
2025-07-02 06:41:18.241 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.241 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.241 else:
2025-07-02 06:41:18.241 # the synch pair is identical
2025-07-02 06:41:18.241 yield ' ' + aelt
2025-07-02 06:41:18.241
2025-07-02 06:41:18.241 # pump out diffs from after the synch point
2025-07-02 06:41:18.241 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.241
2025-07-02 06:41:18.242 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.242 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.242
2025-07-02 06:41:18.242 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.242 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.242 alo = 367, ahi = 1101
2025-07-02 06:41:18.242 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.242 blo = 367, bhi = 1101
2025-07-02 06:41:18.242
2025-07-02 06:41:18.242 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.242 g = []
2025-07-02 06:41:18.242 if alo < ahi:
2025-07-02 06:41:18.242 if blo < bhi:
2025-07-02 06:41:18.242 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.242 else:
2025-07-02 06:41:18.242 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.242 elif blo < bhi:
2025-07-02 06:41:18.242 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.242
2025-07-02 06:41:18.243 > yield from g
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.243 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.243 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.243 alo = 367, ahi = 1101
2025-07-02 06:41:18.243 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.243 blo = 367, bhi = 1101
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.243 r"""
2025-07-02 06:41:18.243 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.243 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.243 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.243 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243 Example:
2025-07-02 06:41:18.244
2025-07-02 06:41:18.244 >>> d = Differ()
2025-07-02 06:41:18.244 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.244 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.244 >>> print(''.join(results), end="")
2025-07-02 06:41:18.244 - abcDefghiJkl
2025-07-02 06:41:18.244 + abcdefGhijkl
2025-07-02 06:41:18.244 """
2025-07-02 06:41:18.244
2025-07-02 06:41:18.244 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.244 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.244 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.244 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.244 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.244
2025-07-02 06:41:18.244 # search for the pair that matches best without being identical
2025-07-02 06:41:18.244 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.244 # on junk -- unless we have to)
2025-07-02 06:41:18.245 for j in range(blo, bhi):
2025-07-02 06:41:18.245 bj = b[j]
2025-07-02 06:41:18.245 cruncher.set_seq2(bj)
2025-07-02 06:41:18.245 for i in range(alo, ahi):
2025-07-02 06:41:18.245 ai = a[i]
2025-07-02 06:41:18.245 if ai == bj:
2025-07-02 06:41:18.245 if eqi is None:
2025-07-02 06:41:18.245 eqi, eqj = i, j
2025-07-02 06:41:18.245 continue
2025-07-02 06:41:18.245 cruncher.set_seq1(ai)
2025-07-02 06:41:18.245 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.245 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.245 # compares by a factor of 3.
2025-07-02 06:41:18.245 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.245 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.245 # of the computation is cached by cruncher
2025-07-02 06:41:18.245 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.245 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.245 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.246 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.246 if best_ratio < cutoff:
2025-07-02 06:41:18.246 # no non-identical "pretty close" pair
2025-07-02 06:41:18.246 if eqi is None:
2025-07-02 06:41:18.246 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.246 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.246 return
2025-07-02 06:41:18.246 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.246 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.246 else:
2025-07-02 06:41:18.246 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.246 eqi = None
2025-07-02 06:41:18.246
2025-07-02 06:41:18.246 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.246 # identical
2025-07-02 06:41:18.246
2025-07-02 06:41:18.246 # pump out diffs from before the synch point
2025-07-02 06:41:18.246 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.246
2025-07-02 06:41:18.246 # do intraline marking on the synch pair
2025-07-02 06:41:18.247 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.247 if eqi is None:
2025-07-02 06:41:18.247 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.247 atags = btags = ""
2025-07-02 06:41:18.247 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.247 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.247 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.247 if tag == 'replace':
2025-07-02 06:41:18.247 atags += '^' * la
2025-07-02 06:41:18.247 btags += '^' * lb
2025-07-02 06:41:18.247 elif tag == 'delete':
2025-07-02 06:41:18.247 atags += '-' * la
2025-07-02 06:41:18.247 elif tag == 'insert':
2025-07-02 06:41:18.247 btags += '+' * lb
2025-07-02 06:41:18.247 elif tag == 'equal':
2025-07-02 06:41:18.247 atags += ' ' * la
2025-07-02 06:41:18.247 btags += ' ' * lb
2025-07-02 06:41:18.247 else:
2025-07-02 06:41:18.248 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.248 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.248 else:
2025-07-02 06:41:18.248 # the synch pair is identical
2025-07-02 06:41:18.248 yield ' ' + aelt
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248 # pump out diffs from after the synch point
2025-07-02 06:41:18.248 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.248 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.248 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.248 alo = 368, ahi = 1101
2025-07-02 06:41:18.248 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.248 blo = 368, bhi = 1101
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.249 g = []
2025-07-02 06:41:18.249 if alo < ahi:
2025-07-02 06:41:18.249 if blo < bhi:
2025-07-02 06:41:18.249 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.249 else:
2025-07-02 06:41:18.249 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.249 elif blo < bhi:
2025-07-02 06:41:18.249 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.249
2025-07-02 06:41:18.249 > yield from g
2025-07-02 06:41:18.249
2025-07-02 06:41:18.249 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.249 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.249
2025-07-02 06:41:18.249 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.249 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.249 alo = 368, ahi = 1101
2025-07-02 06:41:18.249 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.249 blo = 368, bhi = 1101
2025-07-02 06:41:18.249
2025-07-02 06:41:18.250 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.250 r"""
2025-07-02 06:41:18.250 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.250 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.250 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.250 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.250
2025-07-02 06:41:18.250 Example:
2025-07-02 06:41:18.250
2025-07-02 06:41:18.250 >>> d = Differ()
2025-07-02 06:41:18.250 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.250 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.250 >>> print(''.join(results), end="")
2025-07-02 06:41:18.250 - abcDefghiJkl
2025-07-02 06:41:18.250 + abcdefGhijkl
2025-07-02 06:41:18.250 """
2025-07-02 06:41:18.250
2025-07-02 06:41:18.251 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.251 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.251 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.251 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.251 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.251
2025-07-02 06:41:18.251 # search for the pair that matches best without being identical
2025-07-02 06:41:18.251 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.251 # on junk -- unless we have to)
2025-07-02 06:41:18.251 for j in range(blo, bhi):
2025-07-02 06:41:18.251 bj = b[j]
2025-07-02 06:41:18.251 cruncher.set_seq2(bj)
2025-07-02 06:41:18.251 for i in range(alo, ahi):
2025-07-02 06:41:18.251 ai = a[i]
2025-07-02 06:41:18.251 if ai == bj:
2025-07-02 06:41:18.251 if eqi is None:
2025-07-02 06:41:18.251 eqi, eqj = i, j
2025-07-02 06:41:18.251 continue
2025-07-02 06:41:18.251 cruncher.set_seq1(ai)
2025-07-02 06:41:18.251 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.252 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.252 # compares by a factor of 3.
2025-07-02 06:41:18.252 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.252 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.252 # of the computation is cached by cruncher
2025-07-02 06:41:18.252 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.252 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.252 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.252 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.252 if best_ratio < cutoff:
2025-07-02 06:41:18.252 # no non-identical "pretty close" pair
2025-07-02 06:41:18.252 if eqi is None:
2025-07-02 06:41:18.252 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.252 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.252 return
2025-07-02 06:41:18.252 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.252 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.252 else:
2025-07-02 06:41:18.252 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.253 eqi = None
2025-07-02 06:41:18.253
2025-07-02 06:41:18.253 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.253 # identical
2025-07-02 06:41:18.253
2025-07-02 06:41:18.253 # pump out diffs from before the synch point
2025-07-02 06:41:18.253 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.253
2025-07-02 06:41:18.253 # do intraline marking on the synch pair
2025-07-02 06:41:18.253 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.253 if eqi is None:
2025-07-02 06:41:18.253 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.253 atags = btags = ""
2025-07-02 06:41:18.253 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.253 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.253 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.253 if tag == 'replace':
2025-07-02 06:41:18.253 atags += '^' * la
2025-07-02 06:41:18.253 btags += '^' * lb
2025-07-02 06:41:18.253 elif tag == 'delete':
2025-07-02 06:41:18.254 atags += '-' * la
2025-07-02 06:41:18.254 elif tag == 'insert':
2025-07-02 06:41:18.254 btags += '+' * lb
2025-07-02 06:41:18.254 elif tag == 'equal':
2025-07-02 06:41:18.254 atags += ' ' * la
2025-07-02 06:41:18.254 btags += ' ' * lb
2025-07-02 06:41:18.254 else:
2025-07-02 06:41:18.254 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.254 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.254 else:
2025-07-02 06:41:18.254 # the synch pair is identical
2025-07-02 06:41:18.254 yield ' ' + aelt
2025-07-02 06:41:18.254
2025-07-02 06:41:18.254 # pump out diffs from after the synch point
2025-07-02 06:41:18.254 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.254
2025-07-02 06:41:18.254 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.254 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.254
2025-07-02 06:41:18.255 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.255 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.255 alo = 369, ahi = 1101
2025-07-02 06:41:18.255 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.255 blo = 369, bhi = 1101
2025-07-02 06:41:18.255
2025-07-02 06:41:18.255 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.255 g = []
2025-07-02 06:41:18.255 if alo < ahi:
2025-07-02 06:41:18.255 if blo < bhi:
2025-07-02 06:41:18.255 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.255 else:
2025-07-02 06:41:18.255 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.255 elif blo < bhi:
2025-07-02 06:41:18.255 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.255
2025-07-02 06:41:18.255 > yield from g
2025-07-02 06:41:18.255
2025-07-02 06:41:18.255 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.255 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.256 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.256 alo = 369, ahi = 1101
2025-07-02 06:41:18.256 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.256 blo = 369, bhi = 1101
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.256 r"""
2025-07-02 06:41:18.256 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.256 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.256 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.256 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256 Example:
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256 >>> d = Differ()
2025-07-02 06:41:18.256 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.256 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.257 >>> print(''.join(results), end="")
2025-07-02 06:41:18.257 - abcDefghiJkl
2025-07-02 06:41:18.257 + abcdefGhijkl
2025-07-02 06:41:18.257 """
2025-07-02 06:41:18.257
2025-07-02 06:41:18.257 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.257 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.257 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.257 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.257 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.257
2025-07-02 06:41:18.257 # search for the pair that matches best without being identical
2025-07-02 06:41:18.257 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.257 # on junk -- unless we have to)
2025-07-02 06:41:18.257 for j in range(blo, bhi):
2025-07-02 06:41:18.257 bj = b[j]
2025-07-02 06:41:18.257 cruncher.set_seq2(bj)
2025-07-02 06:41:18.257 for i in range(alo, ahi):
2025-07-02 06:41:18.258 ai = a[i]
2025-07-02 06:41:18.258 if ai == bj:
2025-07-02 06:41:18.258 if eqi is None:
2025-07-02 06:41:18.258 eqi, eqj = i, j
2025-07-02 06:41:18.258 continue
2025-07-02 06:41:18.258 cruncher.set_seq1(ai)
2025-07-02 06:41:18.258 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.258 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.258 # compares by a factor of 3.
2025-07-02 06:41:18.258 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.258 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.258 # of the computation is cached by cruncher
2025-07-02 06:41:18.258 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.258 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.258 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.258 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.258 if best_ratio < cutoff:
2025-07-02 06:41:18.258 # no non-identical "pretty close" pair
2025-07-02 06:41:18.258 if eqi is None:
2025-07-02 06:41:18.259 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.259 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.259 return
2025-07-02 06:41:18.259 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.259 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.259 else:
2025-07-02 06:41:18.259 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.259 eqi = None
2025-07-02 06:41:18.259
2025-07-02 06:41:18.259 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.259 # identical
2025-07-02 06:41:18.259
2025-07-02 06:41:18.259 # pump out diffs from before the synch point
2025-07-02 06:41:18.259 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.259
2025-07-02 06:41:18.259 # do intraline marking on the synch pair
2025-07-02 06:41:18.259 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.259 if eqi is None:
2025-07-02 06:41:18.259 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.260 atags = btags = ""
2025-07-02 06:41:18.260 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.260 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.260 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.260 if tag == 'replace':
2025-07-02 06:41:18.260 atags += '^' * la
2025-07-02 06:41:18.260 btags += '^' * lb
2025-07-02 06:41:18.260 elif tag == 'delete':
2025-07-02 06:41:18.260 atags += '-' * la
2025-07-02 06:41:18.260 elif tag == 'insert':
2025-07-02 06:41:18.260 btags += '+' * lb
2025-07-02 06:41:18.260 elif tag == 'equal':
2025-07-02 06:41:18.260 atags += ' ' * la
2025-07-02 06:41:18.260 btags += ' ' * lb
2025-07-02 06:41:18.260 else:
2025-07-02 06:41:18.260 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.260 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.260 else:
2025-07-02 06:41:18.260 # the synch pair is identical
2025-07-02 06:41:18.260 yield ' ' + aelt
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261 # pump out diffs from after the synch point
2025-07-02 06:41:18.261 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.261 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.261 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.261 alo = 370, ahi = 1101
2025-07-02 06:41:18.261 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.261 blo = 370, bhi = 1101
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.261 g = []
2025-07-02 06:41:18.261 if alo < ahi:
2025-07-02 06:41:18.261 if blo < bhi:
2025-07-02 06:41:18.261 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.261 else:
2025-07-02 06:41:18.262 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.262 elif blo < bhi:
2025-07-02 06:41:18.262 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 > yield from g
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.262 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.262 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.262 alo = 370, ahi = 1101
2025-07-02 06:41:18.262 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.262 blo = 370, bhi = 1101
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.262 r"""
2025-07-02 06:41:18.262 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.262 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.263 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.263 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.263
2025-07-02 06:41:18.263 Example:
2025-07-02 06:41:18.263
2025-07-02 06:41:18.263 >>> d = Differ()
2025-07-02 06:41:18.263 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.263 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.263 >>> print(''.join(results), end="")
2025-07-02 06:41:18.263 - abcDefghiJkl
2025-07-02 06:41:18.263 + abcdefGhijkl
2025-07-02 06:41:18.263 """
2025-07-02 06:41:18.263
2025-07-02 06:41:18.263 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.263 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.263 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.263 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.264 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.264
2025-07-02 06:41:18.264 # search for the pair that matches best without being identical
2025-07-02 06:41:18.264 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.264 # on junk -- unless we have to)
2025-07-02 06:41:18.264 for j in range(blo, bhi):
2025-07-02 06:41:18.264 bj = b[j]
2025-07-02 06:41:18.264 cruncher.set_seq2(bj)
2025-07-02 06:41:18.264 for i in range(alo, ahi):
2025-07-02 06:41:18.264 ai = a[i]
2025-07-02 06:41:18.264 if ai == bj:
2025-07-02 06:41:18.264 if eqi is None:
2025-07-02 06:41:18.264 eqi, eqj = i, j
2025-07-02 06:41:18.264 continue
2025-07-02 06:41:18.264 cruncher.set_seq1(ai)
2025-07-02 06:41:18.264 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.264 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.264 # compares by a factor of 3.
2025-07-02 06:41:18.264 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.265 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.265 # of the computation is cached by cruncher
2025-07-02 06:41:18.265 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.265 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.265 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.265 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.265 if best_ratio < cutoff:
2025-07-02 06:41:18.265 # no non-identical "pretty close" pair
2025-07-02 06:41:18.265 if eqi is None:
2025-07-02 06:41:18.265 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.265 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.265 return
2025-07-02 06:41:18.265 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.265 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.265 else:
2025-07-02 06:41:18.265 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.265 eqi = None
2025-07-02 06:41:18.265
2025-07-02 06:41:18.265 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.265 # identical
2025-07-02 06:41:18.266
2025-07-02 06:41:18.266 # pump out diffs from before the synch point
2025-07-02 06:41:18.266 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.266
2025-07-02 06:41:18.266 # do intraline marking on the synch pair
2025-07-02 06:41:18.266 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.266 if eqi is None:
2025-07-02 06:41:18.266 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.266 atags = btags = ""
2025-07-02 06:41:18.266 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.266 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.266 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.266 if tag == 'replace':
2025-07-02 06:41:18.266 atags += '^' * la
2025-07-02 06:41:18.266 btags += '^' * lb
2025-07-02 06:41:18.266 elif tag == 'delete':
2025-07-02 06:41:18.266 atags += '-' * la
2025-07-02 06:41:18.266 elif tag == 'insert':
2025-07-02 06:41:18.266 btags += '+' * lb
2025-07-02 06:41:18.267 elif tag == 'equal':
2025-07-02 06:41:18.267 atags += ' ' * la
2025-07-02 06:41:18.267 btags += ' ' * lb
2025-07-02 06:41:18.267 else:
2025-07-02 06:41:18.267 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.267 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.267 else:
2025-07-02 06:41:18.267 # the synch pair is identical
2025-07-02 06:41:18.267 yield ' ' + aelt
2025-07-02 06:41:18.267
2025-07-02 06:41:18.267 # pump out diffs from after the synch point
2025-07-02 06:41:18.267 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.267
2025-07-02 06:41:18.267 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.267 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.267
2025-07-02 06:41:18.267 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.267 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.267 alo = 371, ahi = 1101
2025-07-02 06:41:18.267 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.268 blo = 371, bhi = 1101
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.268 g = []
2025-07-02 06:41:18.268 if alo < ahi:
2025-07-02 06:41:18.268 if blo < bhi:
2025-07-02 06:41:18.268 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.268 else:
2025-07-02 06:41:18.268 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.268 elif blo < bhi:
2025-07-02 06:41:18.268 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 > yield from g
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.268 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.269 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.269 alo = 371, ahi = 1101
2025-07-02 06:41:18.269 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.269 blo = 371, bhi = 1101
2025-07-02 06:41:18.269
2025-07-02 06:41:18.269 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.269 r"""
2025-07-02 06:41:18.269 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.269 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.269 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.269 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.269
2025-07-02 06:41:18.269 Example:
2025-07-02 06:41:18.269
2025-07-02 06:41:18.269 >>> d = Differ()
2025-07-02 06:41:18.269 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.269 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.269 >>> print(''.join(results), end="")
2025-07-02 06:41:18.269 - abcDefghiJkl
2025-07-02 06:41:18.270 + abcdefGhijkl
2025-07-02 06:41:18.270 """
2025-07-02 06:41:18.270
2025-07-02 06:41:18.270 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.270 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.270 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.270 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.270 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.270
2025-07-02 06:41:18.270 # search for the pair that matches best without being identical
2025-07-02 06:41:18.270 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.270 # on junk -- unless we have to)
2025-07-02 06:41:18.270 for j in range(blo, bhi):
2025-07-02 06:41:18.270 bj = b[j]
2025-07-02 06:41:18.270 cruncher.set_seq2(bj)
2025-07-02 06:41:18.270 for i in range(alo, ahi):
2025-07-02 06:41:18.270 ai = a[i]
2025-07-02 06:41:18.270 if ai == bj:
2025-07-02 06:41:18.271 if eqi is None:
2025-07-02 06:41:18.271 eqi, eqj = i, j
2025-07-02 06:41:18.271 continue
2025-07-02 06:41:18.271 cruncher.set_seq1(ai)
2025-07-02 06:41:18.271 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.271 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.271 # compares by a factor of 3.
2025-07-02 06:41:18.271 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.271 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.271 # of the computation is cached by cruncher
2025-07-02 06:41:18.271 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.271 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.271 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.271 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.271 if best_ratio < cutoff:
2025-07-02 06:41:18.271 # no non-identical "pretty close" pair
2025-07-02 06:41:18.271 if eqi is None:
2025-07-02 06:41:18.271 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.272 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.272 return
2025-07-02 06:41:18.272 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.272 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.272 else:
2025-07-02 06:41:18.272 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.272 eqi = None
2025-07-02 06:41:18.272
2025-07-02 06:41:18.272 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.272 # identical
2025-07-02 06:41:18.272
2025-07-02 06:41:18.272 # pump out diffs from before the synch point
2025-07-02 06:41:18.272 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.272
2025-07-02 06:41:18.272 # do intraline marking on the synch pair
2025-07-02 06:41:18.272 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.272 if eqi is None:
2025-07-02 06:41:18.272 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.272 atags = btags = ""
2025-07-02 06:41:18.272 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.273 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.273 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.273 if tag == 'replace':
2025-07-02 06:41:18.273 atags += '^' * la
2025-07-02 06:41:18.273 btags += '^' * lb
2025-07-02 06:41:18.273 elif tag == 'delete':
2025-07-02 06:41:18.273 atags += '-' * la
2025-07-02 06:41:18.273 elif tag == 'insert':
2025-07-02 06:41:18.273 btags += '+' * lb
2025-07-02 06:41:18.273 elif tag == 'equal':
2025-07-02 06:41:18.273 atags += ' ' * la
2025-07-02 06:41:18.273 btags += ' ' * lb
2025-07-02 06:41:18.273 else:
2025-07-02 06:41:18.273 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.273 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.273 else:
2025-07-02 06:41:18.273 # the synch pair is identical
2025-07-02 06:41:18.273 yield ' ' + aelt
2025-07-02 06:41:18.273
2025-07-02 06:41:18.274 # pump out diffs from after the synch point
2025-07-02 06:41:18.274 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.274
2025-07-02 06:41:18.274 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.274 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.274
2025-07-02 06:41:18.274 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.274 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.274 alo = 372, ahi = 1101
2025-07-02 06:41:18.274 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.274 blo = 372, bhi = 1101
2025-07-02 06:41:18.274
2025-07-02 06:41:18.274 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.274 g = []
2025-07-02 06:41:18.274 if alo < ahi:
2025-07-02 06:41:18.274 if blo < bhi:
2025-07-02 06:41:18.274 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.274 else:
2025-07-02 06:41:18.274 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.275 elif blo < bhi:
2025-07-02 06:41:18.275 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 > yield from g
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.275 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.275 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.275 alo = 372, ahi = 1101
2025-07-02 06:41:18.275 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.275 blo = 372, bhi = 1101
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.275 r"""
2025-07-02 06:41:18.275 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.275 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.275 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.275 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.276
2025-07-02 06:41:18.276 Example:
2025-07-02 06:41:18.276
2025-07-02 06:41:18.276 >>> d = Differ()
2025-07-02 06:41:18.276 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.276 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.276 >>> print(''.join(results), end="")
2025-07-02 06:41:18.276 - abcDefghiJkl
2025-07-02 06:41:18.276 + abcdefGhijkl
2025-07-02 06:41:18.276 """
2025-07-02 06:41:18.276
2025-07-02 06:41:18.276 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.276 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.276 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.276 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.276 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.276
2025-07-02 06:41:18.277 # search for the pair that matches best without being identical
2025-07-02 06:41:18.277 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.277 # on junk -- unless we have to)
2025-07-02 06:41:18.277 for j in range(blo, bhi):
2025-07-02 06:41:18.277 bj = b[j]
2025-07-02 06:41:18.277 cruncher.set_seq2(bj)
2025-07-02 06:41:18.277 for i in range(alo, ahi):
2025-07-02 06:41:18.277 ai = a[i]
2025-07-02 06:41:18.277 if ai == bj:
2025-07-02 06:41:18.277 if eqi is None:
2025-07-02 06:41:18.277 eqi, eqj = i, j
2025-07-02 06:41:18.277 continue
2025-07-02 06:41:18.277 cruncher.set_seq1(ai)
2025-07-02 06:41:18.277 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.277 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.277 # compares by a factor of 3.
2025-07-02 06:41:18.277 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.277 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.277 # of the computation is cached by cruncher
2025-07-02 06:41:18.278 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.278 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.278 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.278 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.278 if best_ratio < cutoff:
2025-07-02 06:41:18.278 # no non-identical "pretty close" pair
2025-07-02 06:41:18.278 if eqi is None:
2025-07-02 06:41:18.278 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.278 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.278 return
2025-07-02 06:41:18.278 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.278 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.278 else:
2025-07-02 06:41:18.278 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.278 eqi = None
2025-07-02 06:41:18.278
2025-07-02 06:41:18.278 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.278 # identical
2025-07-02 06:41:18.279
2025-07-02 06:41:18.279 # pump out diffs from before the synch point
2025-07-02 06:41:18.279 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.279
2025-07-02 06:41:18.279 # do intraline marking on the synch pair
2025-07-02 06:41:18.279 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.279 if eqi is None:
2025-07-02 06:41:18.279 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.279 atags = btags = ""
2025-07-02 06:41:18.279 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.279 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.279 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.279 if tag == 'replace':
2025-07-02 06:41:18.279 atags += '^' * la
2025-07-02 06:41:18.279 btags += '^' * lb
2025-07-02 06:41:18.279 elif tag == 'delete':
2025-07-02 06:41:18.279 atags += '-' * la
2025-07-02 06:41:18.279 elif tag == 'insert':
2025-07-02 06:41:18.279 btags += '+' * lb
2025-07-02 06:41:18.279 elif tag == 'equal':
2025-07-02 06:41:18.280 atags += ' ' * la
2025-07-02 06:41:18.280 btags += ' ' * lb
2025-07-02 06:41:18.280 else:
2025-07-02 06:41:18.280 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.280 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.280 else:
2025-07-02 06:41:18.280 # the synch pair is identical
2025-07-02 06:41:18.280 yield ' ' + aelt
2025-07-02 06:41:18.280
2025-07-02 06:41:18.280 # pump out diffs from after the synch point
2025-07-02 06:41:18.280 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.280
2025-07-02 06:41:18.280 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.280 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.280
2025-07-02 06:41:18.280 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.280 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.280 alo = 373, ahi = 1101
2025-07-02 06:41:18.280 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.281 blo = 373, bhi = 1101
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.281 g = []
2025-07-02 06:41:18.281 if alo < ahi:
2025-07-02 06:41:18.281 if blo < bhi:
2025-07-02 06:41:18.281 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.281 else:
2025-07-02 06:41:18.281 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.281 elif blo < bhi:
2025-07-02 06:41:18.281 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 > yield from g
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.281 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.281 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.282 alo = 373, ahi = 1101
2025-07-02 06:41:18.282 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.282 blo = 373, bhi = 1101
2025-07-02 06:41:18.282
2025-07-02 06:41:18.282 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.282 r"""
2025-07-02 06:41:18.282 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.282 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.282 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.282 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.282
2025-07-02 06:41:18.282 Example:
2025-07-02 06:41:18.282
2025-07-02 06:41:18.282 >>> d = Differ()
2025-07-02 06:41:18.282 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.282 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.282 >>> print(''.join(results), end="")
2025-07-02 06:41:18.283 - abcDefghiJkl
2025-07-02 06:41:18.283 + abcdefGhijkl
2025-07-02 06:41:18.283 """
2025-07-02 06:41:18.283
2025-07-02 06:41:18.283 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.283 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.283 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.283 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.283 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.283
2025-07-02 06:41:18.283 # search for the pair that matches best without being identical
2025-07-02 06:41:18.283 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.283 # on junk -- unless we have to)
2025-07-02 06:41:18.283 for j in range(blo, bhi):
2025-07-02 06:41:18.283 bj = b[j]
2025-07-02 06:41:18.284 cruncher.set_seq2(bj)
2025-07-02 06:41:18.284 for i in range(alo, ahi):
2025-07-02 06:41:18.284 ai = a[i]
2025-07-02 06:41:18.284 if ai == bj:
2025-07-02 06:41:18.284 if eqi is None:
2025-07-02 06:41:18.284 eqi, eqj = i, j
2025-07-02 06:41:18.284 continue
2025-07-02 06:41:18.284 cruncher.set_seq1(ai)
2025-07-02 06:41:18.284 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.284 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.284 # compares by a factor of 3.
2025-07-02 06:41:18.284 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.284 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.284 # of the computation is cached by cruncher
2025-07-02 06:41:18.284 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.284 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.285 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.285 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.285 if best_ratio < cutoff:
2025-07-02 06:41:18.285 # no non-identical "pretty close" pair
2025-07-02 06:41:18.285 if eqi is None:
2025-07-02 06:41:18.285 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.285 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.285 return
2025-07-02 06:41:18.285 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.285 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.285 else:
2025-07-02 06:41:18.285 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.285 eqi = None
2025-07-02 06:41:18.285
2025-07-02 06:41:18.285 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.286 # identical
2025-07-02 06:41:18.286
2025-07-02 06:41:18.286 # pump out diffs from before the synch point
2025-07-02 06:41:18.286 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.286
2025-07-02 06:41:18.286 # do intraline marking on the synch pair
2025-07-02 06:41:18.286 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.286 if eqi is None:
2025-07-02 06:41:18.286 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.286 atags = btags = ""
2025-07-02 06:41:18.286 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.286 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.286 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.286 if tag == 'replace':
2025-07-02 06:41:18.286 atags += '^' * la
2025-07-02 06:41:18.286 btags += '^' * lb
2025-07-02 06:41:18.286 elif tag == 'delete':
2025-07-02 06:41:18.287 atags += '-' * la
2025-07-02 06:41:18.287 elif tag == 'insert':
2025-07-02 06:41:18.287 btags += '+' * lb
2025-07-02 06:41:18.287 elif tag == 'equal':
2025-07-02 06:41:18.287 atags += ' ' * la
2025-07-02 06:41:18.287 btags += ' ' * lb
2025-07-02 06:41:18.287 else:
2025-07-02 06:41:18.287 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.287 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.287 else:
2025-07-02 06:41:18.287 # the synch pair is identical
2025-07-02 06:41:18.287 yield ' ' + aelt
2025-07-02 06:41:18.287
2025-07-02 06:41:18.287 # pump out diffs from after the synch point
2025-07-02 06:41:18.288 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.288
2025-07-02 06:41:18.288 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.288 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.288
2025-07-02 06:41:18.288 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.288 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.288 alo = 374, ahi = 1101
2025-07-02 06:41:18.288 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.288 blo = 374, bhi = 1101
2025-07-02 06:41:18.288
2025-07-02 06:41:18.288 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.288 g = []
2025-07-02 06:41:18.289 if alo < ahi:
2025-07-02 06:41:18.289 if blo < bhi:
2025-07-02 06:41:18.289 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.289 else:
2025-07-02 06:41:18.289 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.289 elif blo < bhi:
2025-07-02 06:41:18.289 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.289
2025-07-02 06:41:18.289 > yield from g
2025-07-02 06:41:18.289
2025-07-02 06:41:18.289 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.289 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.289
2025-07-02 06:41:18.289 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.289 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.289 alo = 374, ahi = 1101
2025-07-02 06:41:18.289 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.290 blo = 374, bhi = 1101
2025-07-02 06:41:18.290
2025-07-02 06:41:18.290 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.290 r"""
2025-07-02 06:41:18.290 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.290 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.290 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.290 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.290
2025-07-02 06:41:18.290 Example:
2025-07-02 06:41:18.290
2025-07-02 06:41:18.290 >>> d = Differ()
2025-07-02 06:41:18.290 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.290 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.290 >>> print(''.join(results), end="")
2025-07-02 06:41:18.290 - abcDefghiJkl
2025-07-02 06:41:18.291 + abcdefGhijkl
2025-07-02 06:41:18.291 """
2025-07-02 06:41:18.291
2025-07-02 06:41:18.291 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.291 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.291 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.291 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.291 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.291
2025-07-02 06:41:18.291 # search for the pair that matches best without being identical
2025-07-02 06:41:18.291 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.291 # on junk -- unless we have to)
2025-07-02 06:41:18.291 for j in range(blo, bhi):
2025-07-02 06:41:18.291 bj = b[j]
2025-07-02 06:41:18.291 cruncher.set_seq2(bj)
2025-07-02 06:41:18.291 for i in range(alo, ahi):
2025-07-02 06:41:18.291 ai = a[i]
2025-07-02 06:41:18.292 if ai == bj:
2025-07-02 06:41:18.292 if eqi is None:
2025-07-02 06:41:18.292 eqi, eqj = i, j
2025-07-02 06:41:18.292 continue
2025-07-02 06:41:18.292 cruncher.set_seq1(ai)
2025-07-02 06:41:18.292 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.292 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.292 # compares by a factor of 3.
2025-07-02 06:41:18.292 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.292 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.292 # of the computation is cached by cruncher
2025-07-02 06:41:18.292 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.292 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.292 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.292 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.292 if best_ratio < cutoff:
2025-07-02 06:41:18.292 # no non-identical "pretty close" pair
2025-07-02 06:41:18.292 if eqi is None:
2025-07-02 06:41:18.293 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.293 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.293 return
2025-07-02 06:41:18.293 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.293 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.293 else:
2025-07-02 06:41:18.293 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.293 eqi = None
2025-07-02 06:41:18.293
2025-07-02 06:41:18.293 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.293 # identical
2025-07-02 06:41:18.293
2025-07-02 06:41:18.293 # pump out diffs from before the synch point
2025-07-02 06:41:18.293 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.293
2025-07-02 06:41:18.293 # do intraline marking on the synch pair
2025-07-02 06:41:18.293 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.294 if eqi is None:
2025-07-02 06:41:18.294 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.294 atags = btags = ""
2025-07-02 06:41:18.294 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.294 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.294 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.294 if tag == 'replace':
2025-07-02 06:41:18.294 atags += '^' * la
2025-07-02 06:41:18.294 btags += '^' * lb
2025-07-02 06:41:18.294 elif tag == 'delete':
2025-07-02 06:41:18.294 atags += '-' * la
2025-07-02 06:41:18.294 elif tag == 'insert':
2025-07-02 06:41:18.294 btags += '+' * lb
2025-07-02 06:41:18.294 elif tag == 'equal':
2025-07-02 06:41:18.294 atags += ' ' * la
2025-07-02 06:41:18.294 btags += ' ' * lb
2025-07-02 06:41:18.294 else:
2025-07-02 06:41:18.294 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.295 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.295 else:
2025-07-02 06:41:18.295 # the synch pair is identical
2025-07-02 06:41:18.295 yield ' ' + aelt
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295 # pump out diffs from after the synch point
2025-07-02 06:41:18.295 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.295 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.295 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.295 alo = 375, ahi = 1101
2025-07-02 06:41:18.295 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.295 blo = 375, bhi = 1101
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.296 g = []
2025-07-02 06:41:18.296 if alo < ahi:
2025-07-02 06:41:18.296 if blo < bhi:
2025-07-02 06:41:18.296 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.296 else:
2025-07-02 06:41:18.296 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.296 elif blo < bhi:
2025-07-02 06:41:18.296 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.296
2025-07-02 06:41:18.296 > yield from g
2025-07-02 06:41:18.296
2025-07-02 06:41:18.296 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.296 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.296
2025-07-02 06:41:18.296 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.296 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.296 alo = 375, ahi = 1101
2025-07-02 06:41:18.297 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.297 blo = 375, bhi = 1101
2025-07-02 06:41:18.297
2025-07-02 06:41:18.297 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.297 r"""
2025-07-02 06:41:18.297 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.297 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.297 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.297 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.297
2025-07-02 06:41:18.297 Example:
2025-07-02 06:41:18.297
2025-07-02 06:41:18.297 >>> d = Differ()
2025-07-02 06:41:18.297 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.297 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.297 >>> print(''.join(results), end="")
2025-07-02 06:41:18.297 - abcDefghiJkl
2025-07-02 06:41:18.298 + abcdefGhijkl
2025-07-02 06:41:18.298 """
2025-07-02 06:41:18.298
2025-07-02 06:41:18.298 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.298 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.298 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.298 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.298 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.298
2025-07-02 06:41:18.298 # search for the pair that matches best without being identical
2025-07-02 06:41:18.298 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.298 # on junk -- unless we have to)
2025-07-02 06:41:18.298 for j in range(blo, bhi):
2025-07-02 06:41:18.298 bj = b[j]
2025-07-02 06:41:18.299 cruncher.set_seq2(bj)
2025-07-02 06:41:18.299 for i in range(alo, ahi):
2025-07-02 06:41:18.299 ai = a[i]
2025-07-02 06:41:18.299 if ai == bj:
2025-07-02 06:41:18.299 if eqi is None:
2025-07-02 06:41:18.299 eqi, eqj = i, j
2025-07-02 06:41:18.299 continue
2025-07-02 06:41:18.299 cruncher.set_seq1(ai)
2025-07-02 06:41:18.299 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.299 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.299 # compares by a factor of 3.
2025-07-02 06:41:18.299 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.299 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.299 # of the computation is cached by cruncher
2025-07-02 06:41:18.299 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.299 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.299 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.299 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.300 if best_ratio < cutoff:
2025-07-02 06:41:18.300 # no non-identical "pretty close" pair
2025-07-02 06:41:18.300 if eqi is None:
2025-07-02 06:41:18.300 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.300 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.300 return
2025-07-02 06:41:18.300 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.300 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.300 else:
2025-07-02 06:41:18.300 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.300 eqi = None
2025-07-02 06:41:18.300
2025-07-02 06:41:18.300 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.300 # identical
2025-07-02 06:41:18.300
2025-07-02 06:41:18.300 # pump out diffs from before the synch point
2025-07-02 06:41:18.300 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.300
2025-07-02 06:41:18.301 # do intraline marking on the synch pair
2025-07-02 06:41:18.301 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.301 if eqi is None:
2025-07-02 06:41:18.301 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.301 atags = btags = ""
2025-07-02 06:41:18.301 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.301 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.301 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.301 if tag == 'replace':
2025-07-02 06:41:18.301 atags += '^' * la
2025-07-02 06:41:18.301 btags += '^' * lb
2025-07-02 06:41:18.301 elif tag == 'delete':
2025-07-02 06:41:18.301 atags += '-' * la
2025-07-02 06:41:18.301 elif tag == 'insert':
2025-07-02 06:41:18.301 btags += '+' * lb
2025-07-02 06:41:18.301 elif tag == 'equal':
2025-07-02 06:41:18.301 atags += ' ' * la
2025-07-02 06:41:18.301 btags += ' ' * lb
2025-07-02 06:41:18.302 else:
2025-07-02 06:41:18.302 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.302 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.302 else:
2025-07-02 06:41:18.302 # the synch pair is identical
2025-07-02 06:41:18.302 yield ' ' + aelt
2025-07-02 06:41:18.302
2025-07-02 06:41:18.302 # pump out diffs from after the synch point
2025-07-02 06:41:18.302 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.302
2025-07-02 06:41:18.302 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.302 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.302
2025-07-02 06:41:18.302 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.302 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.302 alo = 378, ahi = 1101
2025-07-02 06:41:18.302 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.303 blo = 378, bhi = 1101
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.303 g = []
2025-07-02 06:41:18.303 if alo < ahi:
2025-07-02 06:41:18.303 if blo < bhi:
2025-07-02 06:41:18.303 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.303 else:
2025-07-02 06:41:18.303 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.303 elif blo < bhi:
2025-07-02 06:41:18.303 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 > yield from g
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.303 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.304 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.304 alo = 378, ahi = 1101
2025-07-02 06:41:18.304 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.304 blo = 378, bhi = 1101
2025-07-02 06:41:18.304
2025-07-02 06:41:18.304 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.304 r"""
2025-07-02 06:41:18.304 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.304 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.304 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.304 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.304
2025-07-02 06:41:18.304 Example:
2025-07-02 06:41:18.304
2025-07-02 06:41:18.304 >>> d = Differ()
2025-07-02 06:41:18.304 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.304 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.304 >>> print(''.join(results), end="")
2025-07-02 06:41:18.305 - abcDefghiJkl
2025-07-02 06:41:18.305 + abcdefGhijkl
2025-07-02 06:41:18.305 """
2025-07-02 06:41:18.305
2025-07-02 06:41:18.305 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.305 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.305 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.305 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.305 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.305
2025-07-02 06:41:18.305 # search for the pair that matches best without being identical
2025-07-02 06:41:18.305 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.305 # on junk -- unless we have to)
2025-07-02 06:41:18.305 for j in range(blo, bhi):
2025-07-02 06:41:18.305 bj = b[j]
2025-07-02 06:41:18.306 cruncher.set_seq2(bj)
2025-07-02 06:41:18.306 for i in range(alo, ahi):
2025-07-02 06:41:18.306 ai = a[i]
2025-07-02 06:41:18.306 if ai == bj:
2025-07-02 06:41:18.306 if eqi is None:
2025-07-02 06:41:18.306 eqi, eqj = i, j
2025-07-02 06:41:18.306 continue
2025-07-02 06:41:18.306 cruncher.set_seq1(ai)
2025-07-02 06:41:18.306 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.306 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.306 # compares by a factor of 3.
2025-07-02 06:41:18.306 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.306 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.306 # of the computation is cached by cruncher
2025-07-02 06:41:18.306 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.306 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.306 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.306 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.307 if best_ratio < cutoff:
2025-07-02 06:41:18.307 # no non-identical "pretty close" pair
2025-07-02 06:41:18.307 if eqi is None:
2025-07-02 06:41:18.307 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.307 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.307 return
2025-07-02 06:41:18.307 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.307 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.307 else:
2025-07-02 06:41:18.307 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.307 eqi = None
2025-07-02 06:41:18.307
2025-07-02 06:41:18.307 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.307 # identical
2025-07-02 06:41:18.307
2025-07-02 06:41:18.307 # pump out diffs from before the synch point
2025-07-02 06:41:18.307 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.308
2025-07-02 06:41:18.308 # do intraline marking on the synch pair
2025-07-02 06:41:18.308 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.308 if eqi is None:
2025-07-02 06:41:18.308 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.308 atags = btags = ""
2025-07-02 06:41:18.308 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.308 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.308 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.308 if tag == 'replace':
2025-07-02 06:41:18.308 atags += '^' * la
2025-07-02 06:41:18.308 btags += '^' * lb
2025-07-02 06:41:18.308 elif tag == 'delete':
2025-07-02 06:41:18.308 atags += '-' * la
2025-07-02 06:41:18.308 elif tag == 'insert':
2025-07-02 06:41:18.308 btags += '+' * lb
2025-07-02 06:41:18.308 elif tag == 'equal':
2025-07-02 06:41:18.309 atags += ' ' * la
2025-07-02 06:41:18.309 btags += ' ' * lb
2025-07-02 06:41:18.309 else:
2025-07-02 06:41:18.309 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.309 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.309 else:
2025-07-02 06:41:18.309 # the synch pair is identical
2025-07-02 06:41:18.309 yield ' ' + aelt
2025-07-02 06:41:18.309
2025-07-02 06:41:18.309 # pump out diffs from after the synch point
2025-07-02 06:41:18.309 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.309
2025-07-02 06:41:18.309 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.309 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.309
2025-07-02 06:41:18.309 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.309 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.309 alo = 379, ahi = 1101
2025-07-02 06:41:18.310 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.310 blo = 379, bhi = 1101
2025-07-02 06:41:18.310
2025-07-02 06:41:18.310 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.310 g = []
2025-07-02 06:41:18.310 if alo < ahi:
2025-07-02 06:41:18.310 if blo < bhi:
2025-07-02 06:41:18.310 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.310 else:
2025-07-02 06:41:18.310 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.310 elif blo < bhi:
2025-07-02 06:41:18.310 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.310
2025-07-02 06:41:18.310 > yield from g
2025-07-02 06:41:18.310
2025-07-02 06:41:18.310 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.310 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.310
2025-07-02 06:41:18.311 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.311 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.311 alo = 379, ahi = 1101
2025-07-02 06:41:18.311 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.311 blo = 379, bhi = 1101
2025-07-02 06:41:18.311
2025-07-02 06:41:18.311 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.311 r"""
2025-07-02 06:41:18.311 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.311 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.311 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.311 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.311
2025-07-02 06:41:18.311 Example:
2025-07-02 06:41:18.311
2025-07-02 06:41:18.311 >>> d = Differ()
2025-07-02 06:41:18.311 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.311 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.312 >>> print(''.join(results), end="")
2025-07-02 06:41:18.312 - abcDefghiJkl
2025-07-02 06:41:18.312 + abcdefGhijkl
2025-07-02 06:41:18.312 """
2025-07-02 06:41:18.312
2025-07-02 06:41:18.312 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.312 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.312 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.312 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.312 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.312
2025-07-02 06:41:18.312 # search for the pair that matches best without being identical
2025-07-02 06:41:18.312 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.312 # on junk -- unless we have to)
2025-07-02 06:41:18.312 for j in range(blo, bhi):
2025-07-02 06:41:18.312 bj = b[j]
2025-07-02 06:41:18.313 cruncher.set_seq2(bj)
2025-07-02 06:41:18.313 for i in range(alo, ahi):
2025-07-02 06:41:18.313 ai = a[i]
2025-07-02 06:41:18.313 if ai == bj:
2025-07-02 06:41:18.313 if eqi is None:
2025-07-02 06:41:18.313 eqi, eqj = i, j
2025-07-02 06:41:18.313 continue
2025-07-02 06:41:18.313 cruncher.set_seq1(ai)
2025-07-02 06:41:18.313 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.313 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.313 # compares by a factor of 3.
2025-07-02 06:41:18.313 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.313 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.313 # of the computation is cached by cruncher
2025-07-02 06:41:18.313 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.313 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.313 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.313 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.314 if best_ratio < cutoff:
2025-07-02 06:41:18.314 # no non-identical "pretty close" pair
2025-07-02 06:41:18.314 if eqi is None:
2025-07-02 06:41:18.314 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.314 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.314 return
2025-07-02 06:41:18.314 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.314 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.314 else:
2025-07-02 06:41:18.314 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.314 eqi = None
2025-07-02 06:41:18.314
2025-07-02 06:41:18.314 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.314 # identical
2025-07-02 06:41:18.314
2025-07-02 06:41:18.314 # pump out diffs from before the synch point
2025-07-02 06:41:18.314 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.314
2025-07-02 06:41:18.315 # do intraline marking on the synch pair
2025-07-02 06:41:18.315 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.315 if eqi is None:
2025-07-02 06:41:18.315 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.315 atags = btags = ""
2025-07-02 06:41:18.315 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.315 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.315 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.315 if tag == 'replace':
2025-07-02 06:41:18.315 atags += '^' * la
2025-07-02 06:41:18.315 btags += '^' * lb
2025-07-02 06:41:18.315 elif tag == 'delete':
2025-07-02 06:41:18.315 atags += '-' * la
2025-07-02 06:41:18.315 elif tag == 'insert':
2025-07-02 06:41:18.315 btags += '+' * lb
2025-07-02 06:41:18.315 elif tag == 'equal':
2025-07-02 06:41:18.315 atags += ' ' * la
2025-07-02 06:41:18.315 btags += ' ' * lb
2025-07-02 06:41:18.316 else:
2025-07-02 06:41:18.316 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.316 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.316 else:
2025-07-02 06:41:18.316 # the synch pair is identical
2025-07-02 06:41:18.316 yield ' ' + aelt
2025-07-02 06:41:18.316
2025-07-02 06:41:18.316 # pump out diffs from after the synch point
2025-07-02 06:41:18.316 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.316
2025-07-02 06:41:18.316 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.316 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.316
2025-07-02 06:41:18.316 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.316 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.316 alo = 380, ahi = 1101
2025-07-02 06:41:18.316 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.317 blo = 380, bhi = 1101
2025-07-02 06:41:18.317
2025-07-02 06:41:18.317 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.317 g = []
2025-07-02 06:41:18.317 if alo < ahi:
2025-07-02 06:41:18.317 if blo < bhi:
2025-07-02 06:41:18.317 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.317 else:
2025-07-02 06:41:18.317 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.317 elif blo < bhi:
2025-07-02 06:41:18.317 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.317
2025-07-02 06:41:18.317 > yield from g
2025-07-02 06:41:18.317
2025-07-02 06:41:18.317 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.317 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.317
2025-07-02 06:41:18.318 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.318 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.318 alo = 380, ahi = 1101
2025-07-02 06:41:18.318 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.318 blo = 380, bhi = 1101
2025-07-02 06:41:18.318
2025-07-02 06:41:18.318 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.318 r"""
2025-07-02 06:41:18.318 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.318 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.318 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.318 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.318
2025-07-02 06:41:18.318 Example:
2025-07-02 06:41:18.318
2025-07-02 06:41:18.318 >>> d = Differ()
2025-07-02 06:41:18.318 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.319 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.319 >>> print(''.join(results), end="")
2025-07-02 06:41:18.319 - abcDefghiJkl
2025-07-02 06:41:18.319 + abcdefGhijkl
2025-07-02 06:41:18.319 """
2025-07-02 06:41:18.319
2025-07-02 06:41:18.319 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.319 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.319 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.319 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.319 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.319
2025-07-02 06:41:18.319 # search for the pair that matches best without being identical
2025-07-02 06:41:18.319 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.319 # on junk -- unless we have to)
2025-07-02 06:41:18.319 for j in range(blo, bhi):
2025-07-02 06:41:18.320 bj = b[j]
2025-07-02 06:41:18.320 cruncher.set_seq2(bj)
2025-07-02 06:41:18.320 for i in range(alo, ahi):
2025-07-02 06:41:18.320 ai = a[i]
2025-07-02 06:41:18.320 if ai == bj:
2025-07-02 06:41:18.320 if eqi is None:
2025-07-02 06:41:18.320 eqi, eqj = i, j
2025-07-02 06:41:18.320 continue
2025-07-02 06:41:18.320 cruncher.set_seq1(ai)
2025-07-02 06:41:18.320 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.320 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.320 # compares by a factor of 3.
2025-07-02 06:41:18.320 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.320 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.320 # of the computation is cached by cruncher
2025-07-02 06:41:18.320 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.320 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.320 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.321 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.321 if best_ratio < cutoff:
2025-07-02 06:41:18.321 # no non-identical "pretty close" pair
2025-07-02 06:41:18.321 if eqi is None:
2025-07-02 06:41:18.321 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.321 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.321 return
2025-07-02 06:41:18.321 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.321 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.321 else:
2025-07-02 06:41:18.321 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.321 eqi = None
2025-07-02 06:41:18.321
2025-07-02 06:41:18.321 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.321 # identical
2025-07-02 06:41:18.321
2025-07-02 06:41:18.321 # pump out diffs from before the synch point
2025-07-02 06:41:18.321 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.322
2025-07-02 06:41:18.322 # do intraline marking on the synch pair
2025-07-02 06:41:18.322 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.322 if eqi is None:
2025-07-02 06:41:18.322 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.322 atags = btags = ""
2025-07-02 06:41:18.322 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.322 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.322 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.322 if tag == 'replace':
2025-07-02 06:41:18.322 atags += '^' * la
2025-07-02 06:41:18.322 btags += '^' * lb
2025-07-02 06:41:18.322 elif tag == 'delete':
2025-07-02 06:41:18.322 atags += '-' * la
2025-07-02 06:41:18.322 elif tag == 'insert':
2025-07-02 06:41:18.322 btags += '+' * lb
2025-07-02 06:41:18.322 elif tag == 'equal':
2025-07-02 06:41:18.322 atags += ' ' * la
2025-07-02 06:41:18.323 btags += ' ' * lb
2025-07-02 06:41:18.323 else:
2025-07-02 06:41:18.323 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.323 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.323 else:
2025-07-02 06:41:18.323 # the synch pair is identical
2025-07-02 06:41:18.323 yield ' ' + aelt
2025-07-02 06:41:18.323
2025-07-02 06:41:18.323 # pump out diffs from after the synch point
2025-07-02 06:41:18.323 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.323
2025-07-02 06:41:18.323 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.323 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.323
2025-07-02 06:41:18.323 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.324 alo = 381, ahi = 1101
2025-07-02 06:41:18.324 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.324 blo = 381, bhi = 1101
2025-07-02 06:41:18.324
2025-07-02 06:41:18.324 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.324 g = []
2025-07-02 06:41:18.324 if alo < ahi:
2025-07-02 06:41:18.324 if blo < bhi:
2025-07-02 06:41:18.324 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.324 else:
2025-07-02 06:41:18.324 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.324 elif blo < bhi:
2025-07-02 06:41:18.324 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.324
2025-07-02 06:41:18.324 > yield from g
2025-07-02 06:41:18.324
2025-07-02 06:41:18.324 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.325 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.325
2025-07-02 06:41:18.325 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.325 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.325 alo = 381, ahi = 1101
2025-07-02 06:41:18.325 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.325 blo = 381, bhi = 1101
2025-07-02 06:41:18.325
2025-07-02 06:41:18.325 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.325 r"""
2025-07-02 06:41:18.325 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.325 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.325 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.325 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.325
2025-07-02 06:41:18.326 Example:
2025-07-02 06:41:18.326
2025-07-02 06:41:18.326 >>> d = Differ()
2025-07-02 06:41:18.326 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.326 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.326 >>> print(''.join(results), end="")
2025-07-02 06:41:18.326 - abcDefghiJkl
2025-07-02 06:41:18.326 + abcdefGhijkl
2025-07-02 06:41:18.326 """
2025-07-02 06:41:18.326
2025-07-02 06:41:18.326 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.326 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.326 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.326 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.326 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.327
2025-07-02 06:41:18.327 # search for the pair that matches best without being identical
2025-07-02 06:41:18.327 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.327 # on junk -- unless we have to)
2025-07-02 06:41:18.327 for j in range(blo, bhi):
2025-07-02 06:41:18.327 bj = b[j]
2025-07-02 06:41:18.327 cruncher.set_seq2(bj)
2025-07-02 06:41:18.327 for i in range(alo, ahi):
2025-07-02 06:41:18.327 ai = a[i]
2025-07-02 06:41:18.327 if ai == bj:
2025-07-02 06:41:18.327 if eqi is None:
2025-07-02 06:41:18.327 eqi, eqj = i, j
2025-07-02 06:41:18.327 continue
2025-07-02 06:41:18.327 cruncher.set_seq1(ai)
2025-07-02 06:41:18.327 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.327 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.327 # compares by a factor of 3.
2025-07-02 06:41:18.327 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.328 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.328 # of the computation is cached by cruncher
2025-07-02 06:41:18.328 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.328 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.328 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.328 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.328 if best_ratio < cutoff:
2025-07-02 06:41:18.328 # no non-identical "pretty close" pair
2025-07-02 06:41:18.328 if eqi is None:
2025-07-02 06:41:18.328 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.328 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.328 return
2025-07-02 06:41:18.328 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.328 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.328 else:
2025-07-02 06:41:18.328 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.328 eqi = None
2025-07-02 06:41:18.328
2025-07-02 06:41:18.329 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.329 # identical
2025-07-02 06:41:18.329
2025-07-02 06:41:18.329 # pump out diffs from before the synch point
2025-07-02 06:41:18.329 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.329
2025-07-02 06:41:18.329 # do intraline marking on the synch pair
2025-07-02 06:41:18.329 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.329 if eqi is None:
2025-07-02 06:41:18.329 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.329 atags = btags = ""
2025-07-02 06:41:18.329 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.329 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.329 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.329 if tag == 'replace':
2025-07-02 06:41:18.329 atags += '^' * la
2025-07-02 06:41:18.329 btags += '^' * lb
2025-07-02 06:41:18.329 elif tag == 'delete':
2025-07-02 06:41:18.330 atags += '-' * la
2025-07-02 06:41:18.330 elif tag == 'insert':
2025-07-02 06:41:18.330 btags += '+' * lb
2025-07-02 06:41:18.330 elif tag == 'equal':
2025-07-02 06:41:18.330 atags += ' ' * la
2025-07-02 06:41:18.330 btags += ' ' * lb
2025-07-02 06:41:18.330 else:
2025-07-02 06:41:18.330 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.330 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.330 else:
2025-07-02 06:41:18.330 # the synch pair is identical
2025-07-02 06:41:18.330 yield ' ' + aelt
2025-07-02 06:41:18.330
2025-07-02 06:41:18.330 # pump out diffs from after the synch point
2025-07-02 06:41:18.330 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.330
2025-07-02 06:41:18.330 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.330 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.331
2025-07-02 06:41:18.331 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.331 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.331 alo = 382, ahi = 1101
2025-07-02 06:41:18.331 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.331 blo = 382, bhi = 1101
2025-07-02 06:41:18.331
2025-07-02 06:41:18.331 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.331 g = []
2025-07-02 06:41:18.331 if alo < ahi:
2025-07-02 06:41:18.331 if blo < bhi:
2025-07-02 06:41:18.331 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.331 else:
2025-07-02 06:41:18.331 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.331 elif blo < bhi:
2025-07-02 06:41:18.331 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.331
2025-07-02 06:41:18.331 > yield from g
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.332 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.332 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.332 alo = 382, ahi = 1101
2025-07-02 06:41:18.332 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.332 blo = 382, bhi = 1101
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.332 r"""
2025-07-02 06:41:18.332 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.332 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.332 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.332 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332 Example:
2025-07-02 06:41:18.333
2025-07-02 06:41:18.333 >>> d = Differ()
2025-07-02 06:41:18.333 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.333 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.333 >>> print(''.join(results), end="")
2025-07-02 06:41:18.333 - abcDefghiJkl
2025-07-02 06:41:18.333 + abcdefGhijkl
2025-07-02 06:41:18.333 """
2025-07-02 06:41:18.333
2025-07-02 06:41:18.333 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.333 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.333 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.333 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.333 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.333
2025-07-02 06:41:18.333 # search for the pair that matches best without being identical
2025-07-02 06:41:18.333 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.334 # on junk -- unless we have to)
2025-07-02 06:41:18.334 for j in range(blo, bhi):
2025-07-02 06:41:18.334 bj = b[j]
2025-07-02 06:41:18.334 cruncher.set_seq2(bj)
2025-07-02 06:41:18.334 for i in range(alo, ahi):
2025-07-02 06:41:18.334 ai = a[i]
2025-07-02 06:41:18.334 if ai == bj:
2025-07-02 06:41:18.334 if eqi is None:
2025-07-02 06:41:18.334 eqi, eqj = i, j
2025-07-02 06:41:18.334 continue
2025-07-02 06:41:18.334 cruncher.set_seq1(ai)
2025-07-02 06:41:18.334 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.334 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.334 # compares by a factor of 3.
2025-07-02 06:41:18.334 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.334 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.334 # of the computation is cached by cruncher
2025-07-02 06:41:18.334 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.334 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.334 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.335 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.335 if best_ratio < cutoff:
2025-07-02 06:41:18.335 # no non-identical "pretty close" pair
2025-07-02 06:41:18.335 if eqi is None:
2025-07-02 06:41:18.335 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.335 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.335 return
2025-07-02 06:41:18.335 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.335 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.335 else:
2025-07-02 06:41:18.335 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.335 eqi = None
2025-07-02 06:41:18.335
2025-07-02 06:41:18.335 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.335 # identical
2025-07-02 06:41:18.335
2025-07-02 06:41:18.335 # pump out diffs from before the synch point
2025-07-02 06:41:18.335 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.336
2025-07-02 06:41:18.336 # do intraline marking on the synch pair
2025-07-02 06:41:18.336 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.336 if eqi is None:
2025-07-02 06:41:18.336 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.336 atags = btags = ""
2025-07-02 06:41:18.336 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.336 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.336 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.336 if tag == 'replace':
2025-07-02 06:41:18.336 atags += '^' * la
2025-07-02 06:41:18.336 btags += '^' * lb
2025-07-02 06:41:18.336 elif tag == 'delete':
2025-07-02 06:41:18.336 atags += '-' * la
2025-07-02 06:41:18.336 elif tag == 'insert':
2025-07-02 06:41:18.336 btags += '+' * lb
2025-07-02 06:41:18.336 elif tag == 'equal':
2025-07-02 06:41:18.336 atags += ' ' * la
2025-07-02 06:41:18.336 btags += ' ' * lb
2025-07-02 06:41:18.337 else:
2025-07-02 06:41:18.337 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.337 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.337 else:
2025-07-02 06:41:18.337 # the synch pair is identical
2025-07-02 06:41:18.337 yield ' ' + aelt
2025-07-02 06:41:18.337
2025-07-02 06:41:18.337 # pump out diffs from after the synch point
2025-07-02 06:41:18.337 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.337
2025-07-02 06:41:18.337 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.337 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.337
2025-07-02 06:41:18.337 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.337 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.337 alo = 383, ahi = 1101
2025-07-02 06:41:18.337 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.337 blo = 383, bhi = 1101
2025-07-02 06:41:18.337
2025-07-02 06:41:18.338 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.338 g = []
2025-07-02 06:41:18.338 if alo < ahi:
2025-07-02 06:41:18.338 if blo < bhi:
2025-07-02 06:41:18.338 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.338 else:
2025-07-02 06:41:18.338 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.338 elif blo < bhi:
2025-07-02 06:41:18.338 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.338
2025-07-02 06:41:18.338 > yield from g
2025-07-02 06:41:18.338
2025-07-02 06:41:18.338 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.338 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.338
2025-07-02 06:41:18.338 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.338 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.338 alo = 383, ahi = 1101
2025-07-02 06:41:18.338 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.339 blo = 383, bhi = 1101
2025-07-02 06:41:18.339
2025-07-02 06:41:18.339 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.339 r"""
2025-07-02 06:41:18.339 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.339 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.339 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.339 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.339
2025-07-02 06:41:18.339 Example:
2025-07-02 06:41:18.339
2025-07-02 06:41:18.339 >>> d = Differ()
2025-07-02 06:41:18.339 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.339 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.339 >>> print(''.join(results), end="")
2025-07-02 06:41:18.339 - abcDefghiJkl
2025-07-02 06:41:18.339 + abcdefGhijkl
2025-07-02 06:41:18.340 """
2025-07-02 06:41:18.340
2025-07-02 06:41:18.340 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.340 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.340 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.340 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.340 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.340
2025-07-02 06:41:18.340 # search for the pair that matches best without being identical
2025-07-02 06:41:18.340 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.340 # on junk -- unless we have to)
2025-07-02 06:41:18.340 for j in range(blo, bhi):
2025-07-02 06:41:18.340 bj = b[j]
2025-07-02 06:41:18.340 cruncher.set_seq2(bj)
2025-07-02 06:41:18.340 for i in range(alo, ahi):
2025-07-02 06:41:18.340 ai = a[i]
2025-07-02 06:41:18.340 if ai == bj:
2025-07-02 06:41:18.340 if eqi is None:
2025-07-02 06:41:18.340 eqi, eqj = i, j
2025-07-02 06:41:18.341 continue
2025-07-02 06:41:18.341 cruncher.set_seq1(ai)
2025-07-02 06:41:18.341 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.341 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.341 # compares by a factor of 3.
2025-07-02 06:41:18.341 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.341 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.341 # of the computation is cached by cruncher
2025-07-02 06:41:18.341 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.341 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.341 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.341 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.341 if best_ratio < cutoff:
2025-07-02 06:41:18.341 # no non-identical "pretty close" pair
2025-07-02 06:41:18.341 if eqi is None:
2025-07-02 06:41:18.341 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.341 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.341 return
2025-07-02 06:41:18.341 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.342 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.342 else:
2025-07-02 06:41:18.342 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.342 eqi = None
2025-07-02 06:41:18.342
2025-07-02 06:41:18.342 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.342 # identical
2025-07-02 06:41:18.342
2025-07-02 06:41:18.342 # pump out diffs from before the synch point
2025-07-02 06:41:18.342 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.342
2025-07-02 06:41:18.342 # do intraline marking on the synch pair
2025-07-02 06:41:18.342 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.342 if eqi is None:
2025-07-02 06:41:18.342 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.342 atags = btags = ""
2025-07-02 06:41:18.342 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.342 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.342 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.342 if tag == 'replace':
2025-07-02 06:41:18.343 atags += '^' * la
2025-07-02 06:41:18.343 btags += '^' * lb
2025-07-02 06:41:18.343 elif tag == 'delete':
2025-07-02 06:41:18.343 atags += '-' * la
2025-07-02 06:41:18.343 elif tag == 'insert':
2025-07-02 06:41:18.343 btags += '+' * lb
2025-07-02 06:41:18.343 elif tag == 'equal':
2025-07-02 06:41:18.343 atags += ' ' * la
2025-07-02 06:41:18.343 btags += ' ' * lb
2025-07-02 06:41:18.343 else:
2025-07-02 06:41:18.343 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.343 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.343 else:
2025-07-02 06:41:18.343 # the synch pair is identical
2025-07-02 06:41:18.343 yield ' ' + aelt
2025-07-02 06:41:18.343
2025-07-02 06:41:18.343 # pump out diffs from after the synch point
2025-07-02 06:41:18.343 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.343
2025-07-02 06:41:18.343 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.343 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.344 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.344 alo = 384, ahi = 1101
2025-07-02 06:41:18.344 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.344 blo = 384, bhi = 1101
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.344 g = []
2025-07-02 06:41:18.344 if alo < ahi:
2025-07-02 06:41:18.344 if blo < bhi:
2025-07-02 06:41:18.344 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.344 else:
2025-07-02 06:41:18.344 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.344 elif blo < bhi:
2025-07-02 06:41:18.344 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 > yield from g
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.345 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.345
2025-07-02 06:41:18.345 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.345 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.345 alo = 384, ahi = 1101
2025-07-02 06:41:18.345 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.345 blo = 384, bhi = 1101
2025-07-02 06:41:18.345
2025-07-02 06:41:18.345 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.345 r"""
2025-07-02 06:41:18.345 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.345 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.345 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.345 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.345
2025-07-02 06:41:18.345 Example:
2025-07-02 06:41:18.345
2025-07-02 06:41:18.346 >>> d = Differ()
2025-07-02 06:41:18.346 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.346 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.346 >>> print(''.join(results), end="")
2025-07-02 06:41:18.346 - abcDefghiJkl
2025-07-02 06:41:18.346 + abcdefGhijkl
2025-07-02 06:41:18.346 """
2025-07-02 06:41:18.346
2025-07-02 06:41:18.346 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.346 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.346 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.346 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.346 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.346
2025-07-02 06:41:18.346 # search for the pair that matches best without being identical
2025-07-02 06:41:18.346 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.346 # on junk -- unless we have to)
2025-07-02 06:41:18.346 for j in range(blo, bhi):
2025-07-02 06:41:18.347 bj = b[j]
2025-07-02 06:41:18.347 cruncher.set_seq2(bj)
2025-07-02 06:41:18.347 for i in range(alo, ahi):
2025-07-02 06:41:18.347 ai = a[i]
2025-07-02 06:41:18.347 if ai == bj:
2025-07-02 06:41:18.347 if eqi is None:
2025-07-02 06:41:18.347 eqi, eqj = i, j
2025-07-02 06:41:18.347 continue
2025-07-02 06:41:18.347 cruncher.set_seq1(ai)
2025-07-02 06:41:18.347 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.347 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.347 # compares by a factor of 3.
2025-07-02 06:41:18.347 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.347 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.347 # of the computation is cached by cruncher
2025-07-02 06:41:18.347 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.347 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.347 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.347 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.347 if best_ratio < cutoff:
2025-07-02 06:41:18.348 # no non-identical "pretty close" pair
2025-07-02 06:41:18.348 if eqi is None:
2025-07-02 06:41:18.348 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.348 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.348 return
2025-07-02 06:41:18.348 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.348 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.348 else:
2025-07-02 06:41:18.348 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.348 eqi = None
2025-07-02 06:41:18.348
2025-07-02 06:41:18.348 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.348 # identical
2025-07-02 06:41:18.348
2025-07-02 06:41:18.348 # pump out diffs from before the synch point
2025-07-02 06:41:18.348 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.348
2025-07-02 06:41:18.348 # do intraline marking on the synch pair
2025-07-02 06:41:18.348 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.348 if eqi is None:
2025-07-02 06:41:18.349 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.349 atags = btags = ""
2025-07-02 06:41:18.349 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.349 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.349 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.349 if tag == 'replace':
2025-07-02 06:41:18.349 atags += '^' * la
2025-07-02 06:41:18.349 btags += '^' * lb
2025-07-02 06:41:18.349 elif tag == 'delete':
2025-07-02 06:41:18.349 atags += '-' * la
2025-07-02 06:41:18.349 elif tag == 'insert':
2025-07-02 06:41:18.349 btags += '+' * lb
2025-07-02 06:41:18.349 elif tag == 'equal':
2025-07-02 06:41:18.349 atags += ' ' * la
2025-07-02 06:41:18.349 btags += ' ' * lb
2025-07-02 06:41:18.349 else:
2025-07-02 06:41:18.349 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.349 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.349 else:
2025-07-02 06:41:18.349 # the synch pair is identical
2025-07-02 06:41:18.349 yield ' ' + aelt
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350 # pump out diffs from after the synch point
2025-07-02 06:41:18.350 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.350 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.350 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.350 alo = 385, ahi = 1101
2025-07-02 06:41:18.350 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.350 blo = 385, bhi = 1101
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.350 g = []
2025-07-02 06:41:18.350 if alo < ahi:
2025-07-02 06:41:18.350 if blo < bhi:
2025-07-02 06:41:18.350 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.350 else:
2025-07-02 06:41:18.350 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.351 elif blo < bhi:
2025-07-02 06:41:18.351 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 > yield from g
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.351 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.351 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.351 alo = 385, ahi = 1101
2025-07-02 06:41:18.351 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.351 blo = 385, bhi = 1101
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.351 r"""
2025-07-02 06:41:18.351 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.351 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.351 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.351 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352 Example:
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352 >>> d = Differ()
2025-07-02 06:41:18.352 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.352 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.352 >>> print(''.join(results), end="")
2025-07-02 06:41:18.352 - abcDefghiJkl
2025-07-02 06:41:18.352 + abcdefGhijkl
2025-07-02 06:41:18.352 """
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.352 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.352 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.352 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.352 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352 # search for the pair that matches best without being identical
2025-07-02 06:41:18.352 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.353 # on junk -- unless we have to)
2025-07-02 06:41:18.353 for j in range(blo, bhi):
2025-07-02 06:41:18.353 bj = b[j]
2025-07-02 06:41:18.353 cruncher.set_seq2(bj)
2025-07-02 06:41:18.353 for i in range(alo, ahi):
2025-07-02 06:41:18.353 ai = a[i]
2025-07-02 06:41:18.353 if ai == bj:
2025-07-02 06:41:18.353 if eqi is None:
2025-07-02 06:41:18.353 eqi, eqj = i, j
2025-07-02 06:41:18.353 continue
2025-07-02 06:41:18.353 cruncher.set_seq1(ai)
2025-07-02 06:41:18.353 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.353 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.353 # compares by a factor of 3.
2025-07-02 06:41:18.353 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.353 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.353 # of the computation is cached by cruncher
2025-07-02 06:41:18.353 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.353 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.354 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.354 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.354 if best_ratio < cutoff:
2025-07-02 06:41:18.354 # no non-identical "pretty close" pair
2025-07-02 06:41:18.354 if eqi is None:
2025-07-02 06:41:18.354 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.354 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.354 return
2025-07-02 06:41:18.354 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.354 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.354 else:
2025-07-02 06:41:18.354 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.354 eqi = None
2025-07-02 06:41:18.354
2025-07-02 06:41:18.354 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.354 # identical
2025-07-02 06:41:18.354
2025-07-02 06:41:18.354 # pump out diffs from before the synch point
2025-07-02 06:41:18.354 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.355
2025-07-02 06:41:18.355 # do intraline marking on the synch pair
2025-07-02 06:41:18.355 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.355 if eqi is None:
2025-07-02 06:41:18.355 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.355 atags = btags = ""
2025-07-02 06:41:18.355 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.355 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.355 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.355 if tag == 'replace':
2025-07-02 06:41:18.355 atags += '^' * la
2025-07-02 06:41:18.355 btags += '^' * lb
2025-07-02 06:41:18.355 elif tag == 'delete':
2025-07-02 06:41:18.355 atags += '-' * la
2025-07-02 06:41:18.355 elif tag == 'insert':
2025-07-02 06:41:18.355 btags += '+' * lb
2025-07-02 06:41:18.355 elif tag == 'equal':
2025-07-02 06:41:18.355 atags += ' ' * la
2025-07-02 06:41:18.355 btags += ' ' * lb
2025-07-02 06:41:18.355 else:
2025-07-02 06:41:18.356 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.356 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.356 else:
2025-07-02 06:41:18.356 # the synch pair is identical
2025-07-02 06:41:18.356 yield ' ' + aelt
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356 # pump out diffs from after the synch point
2025-07-02 06:41:18.356 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.356 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.356 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.356 alo = 386, ahi = 1101
2025-07-02 06:41:18.356 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.356 blo = 386, bhi = 1101
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.356 g = []
2025-07-02 06:41:18.357 if alo < ahi:
2025-07-02 06:41:18.357 if blo < bhi:
2025-07-02 06:41:18.357 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.357 else:
2025-07-02 06:41:18.357 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.357 elif blo < bhi:
2025-07-02 06:41:18.357 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.357
2025-07-02 06:41:18.357 > yield from g
2025-07-02 06:41:18.357
2025-07-02 06:41:18.357 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.357 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.357
2025-07-02 06:41:18.357 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.357 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.357 alo = 386, ahi = 1101
2025-07-02 06:41:18.357 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.357 blo = 386, bhi = 1101
2025-07-02 06:41:18.358
2025-07-02 06:41:18.358 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.358 r"""
2025-07-02 06:41:18.358 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.358 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.358 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.358 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.358
2025-07-02 06:41:18.358 Example:
2025-07-02 06:41:18.358
2025-07-02 06:41:18.358 >>> d = Differ()
2025-07-02 06:41:18.358 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.358 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.358 >>> print(''.join(results), end="")
2025-07-02 06:41:18.358 - abcDefghiJkl
2025-07-02 06:41:18.358 + abcdefGhijkl
2025-07-02 06:41:18.358 """
2025-07-02 06:41:18.358
2025-07-02 06:41:18.359 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.359 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.359 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.359 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.359 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.359
2025-07-02 06:41:18.359 # search for the pair that matches best without being identical
2025-07-02 06:41:18.359 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.359 # on junk -- unless we have to)
2025-07-02 06:41:18.359 for j in range(blo, bhi):
2025-07-02 06:41:18.359 bj = b[j]
2025-07-02 06:41:18.359 cruncher.set_seq2(bj)
2025-07-02 06:41:18.359 for i in range(alo, ahi):
2025-07-02 06:41:18.359 ai = a[i]
2025-07-02 06:41:18.359 if ai == bj:
2025-07-02 06:41:18.359 if eqi is None:
2025-07-02 06:41:18.359 eqi, eqj = i, j
2025-07-02 06:41:18.359 continue
2025-07-02 06:41:18.359 cruncher.set_seq1(ai)
2025-07-02 06:41:18.359 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.359 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.360 # compares by a factor of 3.
2025-07-02 06:41:18.360 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.360 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.360 # of the computation is cached by cruncher
2025-07-02 06:41:18.360 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.360 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.360 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.360 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.360 if best_ratio < cutoff:
2025-07-02 06:41:18.360 # no non-identical "pretty close" pair
2025-07-02 06:41:18.360 if eqi is None:
2025-07-02 06:41:18.360 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.360 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.360 return
2025-07-02 06:41:18.360 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.360 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.360 else:
2025-07-02 06:41:18.360 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.360 eqi = None
2025-07-02 06:41:18.360
2025-07-02 06:41:18.361 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.361 # identical
2025-07-02 06:41:18.361
2025-07-02 06:41:18.361 # pump out diffs from before the synch point
2025-07-02 06:41:18.361 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.361
2025-07-02 06:41:18.361 # do intraline marking on the synch pair
2025-07-02 06:41:18.361 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.361 if eqi is None:
2025-07-02 06:41:18.361 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.361 atags = btags = ""
2025-07-02 06:41:18.361 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.361 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.361 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.361 if tag == 'replace':
2025-07-02 06:41:18.364 atags += '^' * la
2025-07-02 06:41:18.364 btags += '^' * lb
2025-07-02 06:41:18.364 elif tag == 'delete':
2025-07-02 06:41:18.364 atags += '-' * la
2025-07-02 06:41:18.364 elif tag == 'insert':
2025-07-02 06:41:18.364 btags += '+' * lb
2025-07-02 06:41:18.364 elif tag == 'equal':
2025-07-02 06:41:18.364 atags += ' ' * la
2025-07-02 06:41:18.364 btags += ' ' * lb
2025-07-02 06:41:18.364 else:
2025-07-02 06:41:18.364 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.364 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.364 else:
2025-07-02 06:41:18.364 # the synch pair is identical
2025-07-02 06:41:18.364 yield ' ' + aelt
2025-07-02 06:41:18.364
2025-07-02 06:41:18.364 # pump out diffs from after the synch point
2025-07-02 06:41:18.364 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.364
2025-07-02 06:41:18.365 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.365 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.365
2025-07-02 06:41:18.365 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.365 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.365 alo = 387, ahi = 1101
2025-07-02 06:41:18.365 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.365 blo = 387, bhi = 1101
2025-07-02 06:41:18.365
2025-07-02 06:41:18.365 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.365 g = []
2025-07-02 06:41:18.365 if alo < ahi:
2025-07-02 06:41:18.365 if blo < bhi:
2025-07-02 06:41:18.365 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.365 else:
2025-07-02 06:41:18.365 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.365 elif blo < bhi:
2025-07-02 06:41:18.365 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.365
2025-07-02 06:41:18.366 > yield from g
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.366 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.366 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.366 alo = 387, ahi = 1101
2025-07-02 06:41:18.366 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.366 blo = 387, bhi = 1101
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.366 r"""
2025-07-02 06:41:18.366 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.366 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.366 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.366 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366 Example:
2025-07-02 06:41:18.367
2025-07-02 06:41:18.367 >>> d = Differ()
2025-07-02 06:41:18.367 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.367 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.367 >>> print(''.join(results), end="")
2025-07-02 06:41:18.367 - abcDefghiJkl
2025-07-02 06:41:18.367 + abcdefGhijkl
2025-07-02 06:41:18.367 """
2025-07-02 06:41:18.367
2025-07-02 06:41:18.367 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.367 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.367 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.367 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.367 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.367
2025-07-02 06:41:18.367 # search for the pair that matches best without being identical
2025-07-02 06:41:18.367 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.367 # on junk -- unless we have to)
2025-07-02 06:41:18.368 for j in range(blo, bhi):
2025-07-02 06:41:18.368 bj = b[j]
2025-07-02 06:41:18.368 cruncher.set_seq2(bj)
2025-07-02 06:41:18.368 for i in range(alo, ahi):
2025-07-02 06:41:18.368 ai = a[i]
2025-07-02 06:41:18.368 if ai == bj:
2025-07-02 06:41:18.368 if eqi is None:
2025-07-02 06:41:18.368 eqi, eqj = i, j
2025-07-02 06:41:18.368 continue
2025-07-02 06:41:18.368 cruncher.set_seq1(ai)
2025-07-02 06:41:18.368 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.368 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.368 # compares by a factor of 3.
2025-07-02 06:41:18.368 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.368 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.368 # of the computation is cached by cruncher
2025-07-02 06:41:18.368 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.368 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.368 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.368 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.369 if best_ratio < cutoff:
2025-07-02 06:41:18.369 # no non-identical "pretty close" pair
2025-07-02 06:41:18.369 if eqi is None:
2025-07-02 06:41:18.369 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.369 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.369 return
2025-07-02 06:41:18.369 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.369 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.369 else:
2025-07-02 06:41:18.369 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.369 eqi = None
2025-07-02 06:41:18.369
2025-07-02 06:41:18.369 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.369 # identical
2025-07-02 06:41:18.369
2025-07-02 06:41:18.369 # pump out diffs from before the synch point
2025-07-02 06:41:18.369 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.369
2025-07-02 06:41:18.369 # do intraline marking on the synch pair
2025-07-02 06:41:18.369 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.370 if eqi is None:
2025-07-02 06:41:18.370 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.370 atags = btags = ""
2025-07-02 06:41:18.370 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.370 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.370 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.370 if tag == 'replace':
2025-07-02 06:41:18.370 atags += '^' * la
2025-07-02 06:41:18.370 btags += '^' * lb
2025-07-02 06:41:18.370 elif tag == 'delete':
2025-07-02 06:41:18.370 atags += '-' * la
2025-07-02 06:41:18.370 elif tag == 'insert':
2025-07-02 06:41:18.370 btags += '+' * lb
2025-07-02 06:41:18.370 elif tag == 'equal':
2025-07-02 06:41:18.370 atags += ' ' * la
2025-07-02 06:41:18.370 btags += ' ' * lb
2025-07-02 06:41:18.370 else:
2025-07-02 06:41:18.370 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.370 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.370 else:
2025-07-02 06:41:18.370 # the synch pair is identical
2025-07-02 06:41:18.371 yield ' ' + aelt
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371 # pump out diffs from after the synch point
2025-07-02 06:41:18.371 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.371 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.371 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.371 alo = 388, ahi = 1101
2025-07-02 06:41:18.371 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.371 blo = 388, bhi = 1101
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.371 g = []
2025-07-02 06:41:18.371 if alo < ahi:
2025-07-02 06:41:18.371 if blo < bhi:
2025-07-02 06:41:18.371 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.371 else:
2025-07-02 06:41:18.372 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.372 elif blo < bhi:
2025-07-02 06:41:18.372 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 > yield from g
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.372 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.372 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.372 alo = 388, ahi = 1101
2025-07-02 06:41:18.372 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.372 blo = 388, bhi = 1101
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.372 r"""
2025-07-02 06:41:18.372 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.372 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.372 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.373 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.373
2025-07-02 06:41:18.373 Example:
2025-07-02 06:41:18.373
2025-07-02 06:41:18.373 >>> d = Differ()
2025-07-02 06:41:18.373 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.373 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.373 >>> print(''.join(results), end="")
2025-07-02 06:41:18.373 - abcDefghiJkl
2025-07-02 06:41:18.373 + abcdefGhijkl
2025-07-02 06:41:18.373 """
2025-07-02 06:41:18.373
2025-07-02 06:41:18.373 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.373 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.373 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.374 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.374 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.374
2025-07-02 06:41:18.374 # search for the pair that matches best without being identical
2025-07-02 06:41:18.374 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.374 # on junk -- unless we have to)
2025-07-02 06:41:18.374 for j in range(blo, bhi):
2025-07-02 06:41:18.374 bj = b[j]
2025-07-02 06:41:18.374 cruncher.set_seq2(bj)
2025-07-02 06:41:18.374 for i in range(alo, ahi):
2025-07-02 06:41:18.374 ai = a[i]
2025-07-02 06:41:18.374 if ai == bj:
2025-07-02 06:41:18.374 if eqi is None:
2025-07-02 06:41:18.374 eqi, eqj = i, j
2025-07-02 06:41:18.374 continue
2025-07-02 06:41:18.374 cruncher.set_seq1(ai)
2025-07-02 06:41:18.374 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.374 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.374 # compares by a factor of 3.
2025-07-02 06:41:18.375 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.375 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.375 # of the computation is cached by cruncher
2025-07-02 06:41:18.375 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.375 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.375 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.375 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.375 if best_ratio < cutoff:
2025-07-02 06:41:18.375 # no non-identical "pretty close" pair
2025-07-02 06:41:18.375 if eqi is None:
2025-07-02 06:41:18.375 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.375 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.375 return
2025-07-02 06:41:18.375 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.375 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.375 else:
2025-07-02 06:41:18.375 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.375 eqi = None
2025-07-02 06:41:18.375
2025-07-02 06:41:18.375 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.376 # identical
2025-07-02 06:41:18.376
2025-07-02 06:41:18.376 # pump out diffs from before the synch point
2025-07-02 06:41:18.376 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.376
2025-07-02 06:41:18.376 # do intraline marking on the synch pair
2025-07-02 06:41:18.376 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.376 if eqi is None:
2025-07-02 06:41:18.376 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.376 atags = btags = ""
2025-07-02 06:41:18.376 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.376 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.376 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.376 if tag == 'replace':
2025-07-02 06:41:18.376 atags += '^' * la
2025-07-02 06:41:18.376 btags += '^' * lb
2025-07-02 06:41:18.376 elif tag == 'delete':
2025-07-02 06:41:18.376 atags += '-' * la
2025-07-02 06:41:18.376 elif tag == 'insert':
2025-07-02 06:41:18.376 btags += '+' * lb
2025-07-02 06:41:18.377 elif tag == 'equal':
2025-07-02 06:41:18.377 atags += ' ' * la
2025-07-02 06:41:18.377 btags += ' ' * lb
2025-07-02 06:41:18.377 else:
2025-07-02 06:41:18.377 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.377 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.377 else:
2025-07-02 06:41:18.377 # the synch pair is identical
2025-07-02 06:41:18.377 yield ' ' + aelt
2025-07-02 06:41:18.377
2025-07-02 06:41:18.377 # pump out diffs from after the synch point
2025-07-02 06:41:18.377 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.377
2025-07-02 06:41:18.377 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.377 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.377
2025-07-02 06:41:18.377 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.377 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.377 alo = 389, ahi = 1101
2025-07-02 06:41:18.377 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.378 blo = 389, bhi = 1101
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.378 g = []
2025-07-02 06:41:18.378 if alo < ahi:
2025-07-02 06:41:18.378 if blo < bhi:
2025-07-02 06:41:18.378 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.378 else:
2025-07-02 06:41:18.378 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.378 elif blo < bhi:
2025-07-02 06:41:18.378 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 > yield from g
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.378 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.378 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.378 alo = 389, ahi = 1101
2025-07-02 06:41:18.378 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.379 blo = 389, bhi = 1101
2025-07-02 06:41:18.379
2025-07-02 06:41:18.379 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.379 r"""
2025-07-02 06:41:18.379 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.379 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.379 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.379 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.379
2025-07-02 06:41:18.379 Example:
2025-07-02 06:41:18.379
2025-07-02 06:41:18.379 >>> d = Differ()
2025-07-02 06:41:18.379 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.379 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.379 >>> print(''.join(results), end="")
2025-07-02 06:41:18.379 - abcDefghiJkl
2025-07-02 06:41:18.379 + abcdefGhijkl
2025-07-02 06:41:18.379 """
2025-07-02 06:41:18.380
2025-07-02 06:41:18.380 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.380 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.380 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.380 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.380 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.380
2025-07-02 06:41:18.380 # search for the pair that matches best without being identical
2025-07-02 06:41:18.380 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.380 # on junk -- unless we have to)
2025-07-02 06:41:18.380 for j in range(blo, bhi):
2025-07-02 06:41:18.380 bj = b[j]
2025-07-02 06:41:18.380 cruncher.set_seq2(bj)
2025-07-02 06:41:18.380 for i in range(alo, ahi):
2025-07-02 06:41:18.380 ai = a[i]
2025-07-02 06:41:18.380 if ai == bj:
2025-07-02 06:41:18.380 if eqi is None:
2025-07-02 06:41:18.380 eqi, eqj = i, j
2025-07-02 06:41:18.380 continue
2025-07-02 06:41:18.380 cruncher.set_seq1(ai)
2025-07-02 06:41:18.381 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.381 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.381 # compares by a factor of 3.
2025-07-02 06:41:18.381 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.381 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.381 # of the computation is cached by cruncher
2025-07-02 06:41:18.381 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.381 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.381 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.381 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.381 if best_ratio < cutoff:
2025-07-02 06:41:18.381 # no non-identical "pretty close" pair
2025-07-02 06:41:18.381 if eqi is None:
2025-07-02 06:41:18.381 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.381 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.381 return
2025-07-02 06:41:18.381 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.381 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.381 else:
2025-07-02 06:41:18.381 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.382 eqi = None
2025-07-02 06:41:18.382
2025-07-02 06:41:18.382 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.382 # identical
2025-07-02 06:41:18.382
2025-07-02 06:41:18.382 # pump out diffs from before the synch point
2025-07-02 06:41:18.382 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.382
2025-07-02 06:41:18.382 # do intraline marking on the synch pair
2025-07-02 06:41:18.382 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.382 if eqi is None:
2025-07-02 06:41:18.382 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.382 atags = btags = ""
2025-07-02 06:41:18.382 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.382 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.382 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.382 if tag == 'replace':
2025-07-02 06:41:18.382 atags += '^' * la
2025-07-02 06:41:18.382 btags += '^' * lb
2025-07-02 06:41:18.383 elif tag == 'delete':
2025-07-02 06:41:18.383 atags += '-' * la
2025-07-02 06:41:18.383 elif tag == 'insert':
2025-07-02 06:41:18.383 btags += '+' * lb
2025-07-02 06:41:18.383 elif tag == 'equal':
2025-07-02 06:41:18.383 atags += ' ' * la
2025-07-02 06:41:18.383 btags += ' ' * lb
2025-07-02 06:41:18.383 else:
2025-07-02 06:41:18.383 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.383 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.383 else:
2025-07-02 06:41:18.383 # the synch pair is identical
2025-07-02 06:41:18.383 yield ' ' + aelt
2025-07-02 06:41:18.383
2025-07-02 06:41:18.383 # pump out diffs from after the synch point
2025-07-02 06:41:18.383 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.383
2025-07-02 06:41:18.383 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.383 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.384 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.384 alo = 390, ahi = 1101
2025-07-02 06:41:18.384 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.384 blo = 390, bhi = 1101
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.384 g = []
2025-07-02 06:41:18.384 if alo < ahi:
2025-07-02 06:41:18.384 if blo < bhi:
2025-07-02 06:41:18.384 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.384 else:
2025-07-02 06:41:18.384 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.384 elif blo < bhi:
2025-07-02 06:41:18.384 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 > yield from g
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.385 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.385 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.385 alo = 390, ahi = 1101
2025-07-02 06:41:18.385 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.385 blo = 390, bhi = 1101
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.385 r"""
2025-07-02 06:41:18.385 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.385 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.385 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.385 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385 Example:
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385 >>> d = Differ()
2025-07-02 06:41:18.385 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.385 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.386 >>> print(''.join(results), end="")
2025-07-02 06:41:18.386 - abcDefghiJkl
2025-07-02 06:41:18.386 + abcdefGhijkl
2025-07-02 06:41:18.386 """
2025-07-02 06:41:18.386
2025-07-02 06:41:18.386 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.386 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.386 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.386 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.386 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.386
2025-07-02 06:41:18.386 # search for the pair that matches best without being identical
2025-07-02 06:41:18.386 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.386 # on junk -- unless we have to)
2025-07-02 06:41:18.386 for j in range(blo, bhi):
2025-07-02 06:41:18.386 bj = b[j]
2025-07-02 06:41:18.386 cruncher.set_seq2(bj)
2025-07-02 06:41:18.386 for i in range(alo, ahi):
2025-07-02 06:41:18.386 ai = a[i]
2025-07-02 06:41:18.387 if ai == bj:
2025-07-02 06:41:18.387 if eqi is None:
2025-07-02 06:41:18.387 eqi, eqj = i, j
2025-07-02 06:41:18.387 continue
2025-07-02 06:41:18.387 cruncher.set_seq1(ai)
2025-07-02 06:41:18.387 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.387 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.387 # compares by a factor of 3.
2025-07-02 06:41:18.387 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.387 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.387 # of the computation is cached by cruncher
2025-07-02 06:41:18.387 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.387 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.387 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.387 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.387 if best_ratio < cutoff:
2025-07-02 06:41:18.387 # no non-identical "pretty close" pair
2025-07-02 06:41:18.387 if eqi is None:
2025-07-02 06:41:18.387 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.387 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.388 return
2025-07-02 06:41:18.388 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.388 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.388 else:
2025-07-02 06:41:18.388 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.388 eqi = None
2025-07-02 06:41:18.388
2025-07-02 06:41:18.388 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.388 # identical
2025-07-02 06:41:18.388
2025-07-02 06:41:18.388 # pump out diffs from before the synch point
2025-07-02 06:41:18.388 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.388
2025-07-02 06:41:18.388 # do intraline marking on the synch pair
2025-07-02 06:41:18.388 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.388 if eqi is None:
2025-07-02 06:41:18.388 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.388 atags = btags = ""
2025-07-02 06:41:18.388 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.389 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.389 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.389 if tag == 'replace':
2025-07-02 06:41:18.389 atags += '^' * la
2025-07-02 06:41:18.389 btags += '^' * lb
2025-07-02 06:41:18.389 elif tag == 'delete':
2025-07-02 06:41:18.389 atags += '-' * la
2025-07-02 06:41:18.389 elif tag == 'insert':
2025-07-02 06:41:18.389 btags += '+' * lb
2025-07-02 06:41:18.389 elif tag == 'equal':
2025-07-02 06:41:18.389 atags += ' ' * la
2025-07-02 06:41:18.389 btags += ' ' * lb
2025-07-02 06:41:18.389 else:
2025-07-02 06:41:18.389 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.389 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.389 else:
2025-07-02 06:41:18.389 # the synch pair is identical
2025-07-02 06:41:18.389 yield ' ' + aelt
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390 # pump out diffs from after the synch point
2025-07-02 06:41:18.390 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.390 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.390 alo = 391, ahi = 1101
2025-07-02 06:41:18.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.390 blo = 391, bhi = 1101
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.390 g = []
2025-07-02 06:41:18.390 if alo < ahi:
2025-07-02 06:41:18.390 if blo < bhi:
2025-07-02 06:41:18.390 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.391 else:
2025-07-02 06:41:18.391 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.391 elif blo < bhi:
2025-07-02 06:41:18.391 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 > yield from g
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.391 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.391 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.391 alo = 391, ahi = 1101
2025-07-02 06:41:18.391 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.391 blo = 391, bhi = 1101
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.391 r"""
2025-07-02 06:41:18.391 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.392 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.392 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.392 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.392
2025-07-02 06:41:18.392 Example:
2025-07-02 06:41:18.392
2025-07-02 06:41:18.392 >>> d = Differ()
2025-07-02 06:41:18.392 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.392 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.392 >>> print(''.join(results), end="")
2025-07-02 06:41:18.392 - abcDefghiJkl
2025-07-02 06:41:18.392 + abcdefGhijkl
2025-07-02 06:41:18.392 """
2025-07-02 06:41:18.392
2025-07-02 06:41:18.392 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.392 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.392 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.393 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.393 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.393
2025-07-02 06:41:18.393 # search for the pair that matches best without being identical
2025-07-02 06:41:18.393 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.393 # on junk -- unless we have to)
2025-07-02 06:41:18.393 for j in range(blo, bhi):
2025-07-02 06:41:18.393 bj = b[j]
2025-07-02 06:41:18.393 cruncher.set_seq2(bj)
2025-07-02 06:41:18.393 for i in range(alo, ahi):
2025-07-02 06:41:18.393 ai = a[i]
2025-07-02 06:41:18.393 if ai == bj:
2025-07-02 06:41:18.393 if eqi is None:
2025-07-02 06:41:18.393 eqi, eqj = i, j
2025-07-02 06:41:18.393 continue
2025-07-02 06:41:18.393 cruncher.set_seq1(ai)
2025-07-02 06:41:18.393 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.393 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.393 # compares by a factor of 3.
2025-07-02 06:41:18.394 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.394 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.394 # of the computation is cached by cruncher
2025-07-02 06:41:18.394 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.394 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.394 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.394 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.394 if best_ratio < cutoff:
2025-07-02 06:41:18.394 # no non-identical "pretty close" pair
2025-07-02 06:41:18.394 if eqi is None:
2025-07-02 06:41:18.394 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.394 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.394 return
2025-07-02 06:41:18.394 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.394 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.394 else:
2025-07-02 06:41:18.394 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.394 eqi = None
2025-07-02 06:41:18.394
2025-07-02 06:41:18.394 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.395 # identical
2025-07-02 06:41:18.395
2025-07-02 06:41:18.395 # pump out diffs from before the synch point
2025-07-02 06:41:18.395 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.395
2025-07-02 06:41:18.395 # do intraline marking on the synch pair
2025-07-02 06:41:18.395 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.395 if eqi is None:
2025-07-02 06:41:18.395 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.395 atags = btags = ""
2025-07-02 06:41:18.395 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.395 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.395 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.395 if tag == 'replace':
2025-07-02 06:41:18.395 atags += '^' * la
2025-07-02 06:41:18.395 btags += '^' * lb
2025-07-02 06:41:18.395 elif tag == 'delete':
2025-07-02 06:41:18.395 atags += '-' * la
2025-07-02 06:41:18.395 elif tag == 'insert':
2025-07-02 06:41:18.395 btags += '+' * lb
2025-07-02 06:41:18.395 elif tag == 'equal':
2025-07-02 06:41:18.396 atags += ' ' * la
2025-07-02 06:41:18.396 btags += ' ' * lb
2025-07-02 06:41:18.396 else:
2025-07-02 06:41:18.396 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.396 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.396 else:
2025-07-02 06:41:18.396 # the synch pair is identical
2025-07-02 06:41:18.396 yield ' ' + aelt
2025-07-02 06:41:18.396
2025-07-02 06:41:18.396 # pump out diffs from after the synch point
2025-07-02 06:41:18.396 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.396
2025-07-02 06:41:18.396 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.396
2025-07-02 06:41:18.396 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.396 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.396 alo = 392, ahi = 1101
2025-07-02 06:41:18.396 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.397 blo = 392, bhi = 1101
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.397 g = []
2025-07-02 06:41:18.397 if alo < ahi:
2025-07-02 06:41:18.397 if blo < bhi:
2025-07-02 06:41:18.397 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.397 else:
2025-07-02 06:41:18.397 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.397 elif blo < bhi:
2025-07-02 06:41:18.397 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 > yield from g
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.397 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.397 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.397 alo = 392, ahi = 1101
2025-07-02 06:41:18.397 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.398 blo = 392, bhi = 1101
2025-07-02 06:41:18.398
2025-07-02 06:41:18.398 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.398 r"""
2025-07-02 06:41:18.398 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.398 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.398 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.398 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.398
2025-07-02 06:41:18.398 Example:
2025-07-02 06:41:18.398
2025-07-02 06:41:18.398 >>> d = Differ()
2025-07-02 06:41:18.398 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.398 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.398 >>> print(''.join(results), end="")
2025-07-02 06:41:18.398 - abcDefghiJkl
2025-07-02 06:41:18.398 + abcdefGhijkl
2025-07-02 06:41:18.398 """
2025-07-02 06:41:18.399
2025-07-02 06:41:18.399 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.399 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.399 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.399 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.399 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.399
2025-07-02 06:41:18.399 # search for the pair that matches best without being identical
2025-07-02 06:41:18.399 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.399 # on junk -- unless we have to)
2025-07-02 06:41:18.399 for j in range(blo, bhi):
2025-07-02 06:41:18.399 bj = b[j]
2025-07-02 06:41:18.399 cruncher.set_seq2(bj)
2025-07-02 06:41:18.399 for i in range(alo, ahi):
2025-07-02 06:41:18.399 ai = a[i]
2025-07-02 06:41:18.399 if ai == bj:
2025-07-02 06:41:18.399 if eqi is None:
2025-07-02 06:41:18.399 eqi, eqj = i, j
2025-07-02 06:41:18.400 continue
2025-07-02 06:41:18.400 cruncher.set_seq1(ai)
2025-07-02 06:41:18.400 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.400 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.400 # compares by a factor of 3.
2025-07-02 06:41:18.400 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.400 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.400 # of the computation is cached by cruncher
2025-07-02 06:41:18.400 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.400 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.400 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.400 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.400 if best_ratio < cutoff:
2025-07-02 06:41:18.400 # no non-identical "pretty close" pair
2025-07-02 06:41:18.400 if eqi is None:
2025-07-02 06:41:18.400 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.400 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.400 return
2025-07-02 06:41:18.400 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.400 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.401 else:
2025-07-02 06:41:18.401 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.401 eqi = None
2025-07-02 06:41:18.401
2025-07-02 06:41:18.401 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.401 # identical
2025-07-02 06:41:18.401
2025-07-02 06:41:18.401 # pump out diffs from before the synch point
2025-07-02 06:41:18.401 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.401
2025-07-02 06:41:18.401 # do intraline marking on the synch pair
2025-07-02 06:41:18.401 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.401 if eqi is None:
2025-07-02 06:41:18.401 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.401 atags = btags = ""
2025-07-02 06:41:18.401 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.401 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.401 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.401 if tag == 'replace':
2025-07-02 06:41:18.402 atags += '^' * la
2025-07-02 06:41:18.402 btags += '^' * lb
2025-07-02 06:41:18.402 elif tag == 'delete':
2025-07-02 06:41:18.402 atags += '-' * la
2025-07-02 06:41:18.402 elif tag == 'insert':
2025-07-02 06:41:18.402 btags += '+' * lb
2025-07-02 06:41:18.402 elif tag == 'equal':
2025-07-02 06:41:18.402 atags += ' ' * la
2025-07-02 06:41:18.402 btags += ' ' * lb
2025-07-02 06:41:18.402 else:
2025-07-02 06:41:18.402 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.402 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.402 else:
2025-07-02 06:41:18.402 # the synch pair is identical
2025-07-02 06:41:18.402 yield ' ' + aelt
2025-07-02 06:41:18.402
2025-07-02 06:41:18.402 # pump out diffs from after the synch point
2025-07-02 06:41:18.402 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.402
2025-07-02 06:41:18.402 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.403 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.403
2025-07-02 06:41:18.403 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.403 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.403 alo = 393, ahi = 1101
2025-07-02 06:41:18.403 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.403 blo = 393, bhi = 1101
2025-07-02 06:41:18.403
2025-07-02 06:41:18.403 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.403 g = []
2025-07-02 06:41:18.403 if alo < ahi:
2025-07-02 06:41:18.403 if blo < bhi:
2025-07-02 06:41:18.403 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.403 else:
2025-07-02 06:41:18.403 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.403 elif blo < bhi:
2025-07-02 06:41:18.403 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.403
2025-07-02 06:41:18.403 > yield from g
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.404 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.404 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.404 alo = 393, ahi = 1101
2025-07-02 06:41:18.404 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.404 blo = 393, bhi = 1101
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.404 r"""
2025-07-02 06:41:18.404 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.404 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.404 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.404 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 Example:
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 >>> d = Differ()
2025-07-02 06:41:18.405 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.405 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.405 >>> print(''.join(results), end="")
2025-07-02 06:41:18.405 - abcDefghiJkl
2025-07-02 06:41:18.405 + abcdefGhijkl
2025-07-02 06:41:18.405 """
2025-07-02 06:41:18.405
2025-07-02 06:41:18.405 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.405 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.405 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.405 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.405 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.405
2025-07-02 06:41:18.405 # search for the pair that matches best without being identical
2025-07-02 06:41:18.405 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.405 # on junk -- unless we have to)
2025-07-02 06:41:18.405 for j in range(blo, bhi):
2025-07-02 06:41:18.406 bj = b[j]
2025-07-02 06:41:18.406 cruncher.set_seq2(bj)
2025-07-02 06:41:18.406 for i in range(alo, ahi):
2025-07-02 06:41:18.406 ai = a[i]
2025-07-02 06:41:18.406 if ai == bj:
2025-07-02 06:41:18.406 if eqi is None:
2025-07-02 06:41:18.406 eqi, eqj = i, j
2025-07-02 06:41:18.406 continue
2025-07-02 06:41:18.406 cruncher.set_seq1(ai)
2025-07-02 06:41:18.406 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.406 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.406 # compares by a factor of 3.
2025-07-02 06:41:18.406 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.406 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.406 # of the computation is cached by cruncher
2025-07-02 06:41:18.406 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.406 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.406 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.406 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.407 if best_ratio < cutoff:
2025-07-02 06:41:18.407 # no non-identical "pretty close" pair
2025-07-02 06:41:18.407 if eqi is None:
2025-07-02 06:41:18.407 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.407 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.407 return
2025-07-02 06:41:18.407 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.407 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.407 else:
2025-07-02 06:41:18.407 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.407 eqi = None
2025-07-02 06:41:18.407
2025-07-02 06:41:18.407 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.407 # identical
2025-07-02 06:41:18.407
2025-07-02 06:41:18.407 # pump out diffs from before the synch point
2025-07-02 06:41:18.407 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.407
2025-07-02 06:41:18.407 # do intraline marking on the synch pair
2025-07-02 06:41:18.407 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.407 if eqi is None:
2025-07-02 06:41:18.408 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.408 atags = btags = ""
2025-07-02 06:41:18.408 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.408 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.408 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.408 if tag == 'replace':
2025-07-02 06:41:18.408 atags += '^' * la
2025-07-02 06:41:18.408 btags += '^' * lb
2025-07-02 06:41:18.408 elif tag == 'delete':
2025-07-02 06:41:18.408 atags += '-' * la
2025-07-02 06:41:18.408 elif tag == 'insert':
2025-07-02 06:41:18.408 btags += '+' * lb
2025-07-02 06:41:18.408 elif tag == 'equal':
2025-07-02 06:41:18.408 atags += ' ' * la
2025-07-02 06:41:18.408 btags += ' ' * lb
2025-07-02 06:41:18.408 else:
2025-07-02 06:41:18.408 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.408 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.409 else:
2025-07-02 06:41:18.409 # the synch pair is identical
2025-07-02 06:41:18.409 yield ' ' + aelt
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 # pump out diffs from after the synch point
2025-07-02 06:41:18.409 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.409 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.409 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.409 alo = 394, ahi = 1101
2025-07-02 06:41:18.409 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.409 blo = 394, bhi = 1101
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.409 g = []
2025-07-02 06:41:18.409 if alo < ahi:
2025-07-02 06:41:18.409 if blo < bhi:
2025-07-02 06:41:18.409 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.409 else:
2025-07-02 06:41:18.409 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.409 elif blo < bhi:
2025-07-02 06:41:18.409 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 > yield from g
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.410 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.410 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.410 alo = 394, ahi = 1101
2025-07-02 06:41:18.410 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.410 blo = 394, bhi = 1101
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.410 r"""
2025-07-02 06:41:18.410 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.410 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.410 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.410 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410 Example:
2025-07-02 06:41:18.410
2025-07-02 06:41:18.411 >>> d = Differ()
2025-07-02 06:41:18.411 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.411 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.411 >>> print(''.join(results), end="")
2025-07-02 06:41:18.411 - abcDefghiJkl
2025-07-02 06:41:18.411 + abcdefGhijkl
2025-07-02 06:41:18.411 """
2025-07-02 06:41:18.411
2025-07-02 06:41:18.411 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.411 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.411 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.411 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.411 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.411
2025-07-02 06:41:18.411 # search for the pair that matches best without being identical
2025-07-02 06:41:18.411 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.411 # on junk -- unless we have to)
2025-07-02 06:41:18.411 for j in range(blo, bhi):
2025-07-02 06:41:18.412 bj = b[j]
2025-07-02 06:41:18.412 cruncher.set_seq2(bj)
2025-07-02 06:41:18.412 for i in range(alo, ahi):
2025-07-02 06:41:18.412 ai = a[i]
2025-07-02 06:41:18.412 if ai == bj:
2025-07-02 06:41:18.412 if eqi is None:
2025-07-02 06:41:18.412 eqi, eqj = i, j
2025-07-02 06:41:18.412 continue
2025-07-02 06:41:18.412 cruncher.set_seq1(ai)
2025-07-02 06:41:18.412 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.412 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.412 # compares by a factor of 3.
2025-07-02 06:41:18.412 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.412 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.412 # of the computation is cached by cruncher
2025-07-02 06:41:18.412 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.412 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.412 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.412 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.412 if best_ratio < cutoff:
2025-07-02 06:41:18.413 # no non-identical "pretty close" pair
2025-07-02 06:41:18.413 if eqi is None:
2025-07-02 06:41:18.413 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.413 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.413 return
2025-07-02 06:41:18.413 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.413 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.413 else:
2025-07-02 06:41:18.413 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.413 eqi = None
2025-07-02 06:41:18.413
2025-07-02 06:41:18.413 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.413 # identical
2025-07-02 06:41:18.413
2025-07-02 06:41:18.413 # pump out diffs from before the synch point
2025-07-02 06:41:18.413 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.413
2025-07-02 06:41:18.413 # do intraline marking on the synch pair
2025-07-02 06:41:18.413 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.414 if eqi is None:
2025-07-02 06:41:18.414 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.414 atags = btags = ""
2025-07-02 06:41:18.414 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.414 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.414 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.414 if tag == 'replace':
2025-07-02 06:41:18.414 atags += '^' * la
2025-07-02 06:41:18.414 btags += '^' * lb
2025-07-02 06:41:18.414 elif tag == 'delete':
2025-07-02 06:41:18.414 atags += '-' * la
2025-07-02 06:41:18.414 elif tag == 'insert':
2025-07-02 06:41:18.414 btags += '+' * lb
2025-07-02 06:41:18.414 elif tag == 'equal':
2025-07-02 06:41:18.414 atags += ' ' * la
2025-07-02 06:41:18.414 btags += ' ' * lb
2025-07-02 06:41:18.414 else:
2025-07-02 06:41:18.414 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.414 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.414 else:
2025-07-02 06:41:18.415 # the synch pair is identical
2025-07-02 06:41:18.415 yield ' ' + aelt
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415 # pump out diffs from after the synch point
2025-07-02 06:41:18.415 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.415 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.415 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.415 alo = 395, ahi = 1101
2025-07-02 06:41:18.415 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.415 blo = 395, bhi = 1101
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.415 g = []
2025-07-02 06:41:18.415 if alo < ahi:
2025-07-02 06:41:18.415 if blo < bhi:
2025-07-02 06:41:18.415 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.416 else:
2025-07-02 06:41:18.416 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.416 elif blo < bhi:
2025-07-02 06:41:18.416 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 > yield from g
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.416 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.416 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.416 alo = 395, ahi = 1101
2025-07-02 06:41:18.416 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.416 blo = 395, bhi = 1101
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.416 r"""
2025-07-02 06:41:18.417 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.417 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.417 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.417 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.417
2025-07-02 06:41:18.417 Example:
2025-07-02 06:41:18.417
2025-07-02 06:41:18.417 >>> d = Differ()
2025-07-02 06:41:18.417 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.417 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.417 >>> print(''.join(results), end="")
2025-07-02 06:41:18.417 - abcDefghiJkl
2025-07-02 06:41:18.417 + abcdefGhijkl
2025-07-02 06:41:18.417 """
2025-07-02 06:41:18.417
2025-07-02 06:41:18.417 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.417 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.418 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.418 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.418 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.418
2025-07-02 06:41:18.418 # search for the pair that matches best without being identical
2025-07-02 06:41:18.418 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.418 # on junk -- unless we have to)
2025-07-02 06:41:18.418 for j in range(blo, bhi):
2025-07-02 06:41:18.418 bj = b[j]
2025-07-02 06:41:18.418 cruncher.set_seq2(bj)
2025-07-02 06:41:18.418 for i in range(alo, ahi):
2025-07-02 06:41:18.418 ai = a[i]
2025-07-02 06:41:18.418 if ai == bj:
2025-07-02 06:41:18.418 if eqi is None:
2025-07-02 06:41:18.418 eqi, eqj = i, j
2025-07-02 06:41:18.418 continue
2025-07-02 06:41:18.418 cruncher.set_seq1(ai)
2025-07-02 06:41:18.418 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.418 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.418 # compares by a factor of 3.
2025-07-02 06:41:18.419 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.419 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.419 # of the computation is cached by cruncher
2025-07-02 06:41:18.419 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.419 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.419 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.419 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.419 if best_ratio < cutoff:
2025-07-02 06:41:18.419 # no non-identical "pretty close" pair
2025-07-02 06:41:18.419 if eqi is None:
2025-07-02 06:41:18.419 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.419 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.419 return
2025-07-02 06:41:18.419 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.419 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.419 else:
2025-07-02 06:41:18.419 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.419 eqi = None
2025-07-02 06:41:18.420
2025-07-02 06:41:18.420 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.420 # identical
2025-07-02 06:41:18.420
2025-07-02 06:41:18.420 # pump out diffs from before the synch point
2025-07-02 06:41:18.420 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.420
2025-07-02 06:41:18.420 # do intraline marking on the synch pair
2025-07-02 06:41:18.420 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.420 if eqi is None:
2025-07-02 06:41:18.420 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.420 atags = btags = ""
2025-07-02 06:41:18.420 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.420 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.420 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.420 if tag == 'replace':
2025-07-02 06:41:18.420 atags += '^' * la
2025-07-02 06:41:18.420 btags += '^' * lb
2025-07-02 06:41:18.421 elif tag == 'delete':
2025-07-02 06:41:18.421 atags += '-' * la
2025-07-02 06:41:18.421 elif tag == 'insert':
2025-07-02 06:41:18.421 btags += '+' * lb
2025-07-02 06:41:18.421 elif tag == 'equal':
2025-07-02 06:41:18.421 atags += ' ' * la
2025-07-02 06:41:18.421 btags += ' ' * lb
2025-07-02 06:41:18.421 else:
2025-07-02 06:41:18.421 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.421 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.421 else:
2025-07-02 06:41:18.421 # the synch pair is identical
2025-07-02 06:41:18.421 yield ' ' + aelt
2025-07-02 06:41:18.421
2025-07-02 06:41:18.421 # pump out diffs from after the synch point
2025-07-02 06:41:18.421 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.421
2025-07-02 06:41:18.421 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.421 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.421
2025-07-02 06:41:18.422 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.422 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.422 alo = 396, ahi = 1101
2025-07-02 06:41:18.422 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.422 blo = 396, bhi = 1101
2025-07-02 06:41:18.422
2025-07-02 06:41:18.422 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.422 g = []
2025-07-02 06:41:18.422 if alo < ahi:
2025-07-02 06:41:18.422 if blo < bhi:
2025-07-02 06:41:18.422 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.422 else:
2025-07-02 06:41:18.422 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.422 elif blo < bhi:
2025-07-02 06:41:18.422 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.422
2025-07-02 06:41:18.422 > yield from g
2025-07-02 06:41:18.422
2025-07-02 06:41:18.422 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.422 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.423 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.423 alo = 396, ahi = 1101
2025-07-02 06:41:18.423 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.423 blo = 396, bhi = 1101
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.423 r"""
2025-07-02 06:41:18.423 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.423 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.423 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.423 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423 Example:
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423 >>> d = Differ()
2025-07-02 06:41:18.423 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.423 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.424 >>> print(''.join(results), end="")
2025-07-02 06:41:18.424 - abcDefghiJkl
2025-07-02 06:41:18.424 + abcdefGhijkl
2025-07-02 06:41:18.424 """
2025-07-02 06:41:18.424
2025-07-02 06:41:18.424 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.424 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.424 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.424 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.424 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.424
2025-07-02 06:41:18.424 # search for the pair that matches best without being identical
2025-07-02 06:41:18.424 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.424 # on junk -- unless we have to)
2025-07-02 06:41:18.424 for j in range(blo, bhi):
2025-07-02 06:41:18.424 bj = b[j]
2025-07-02 06:41:18.424 cruncher.set_seq2(bj)
2025-07-02 06:41:18.424 for i in range(alo, ahi):
2025-07-02 06:41:18.425 ai = a[i]
2025-07-02 06:41:18.425 if ai == bj:
2025-07-02 06:41:18.425 if eqi is None:
2025-07-02 06:41:18.425 eqi, eqj = i, j
2025-07-02 06:41:18.425 continue
2025-07-02 06:41:18.425 cruncher.set_seq1(ai)
2025-07-02 06:41:18.425 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.425 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.425 # compares by a factor of 3.
2025-07-02 06:41:18.425 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.425 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.425 # of the computation is cached by cruncher
2025-07-02 06:41:18.425 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.425 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.425 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.425 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.425 if best_ratio < cutoff:
2025-07-02 06:41:18.425 # no non-identical "pretty close" pair
2025-07-02 06:41:18.425 if eqi is None:
2025-07-02 06:41:18.426 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.426 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.426 return
2025-07-02 06:41:18.426 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.426 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.426 else:
2025-07-02 06:41:18.426 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.426 eqi = None
2025-07-02 06:41:18.426
2025-07-02 06:41:18.426 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.426 # identical
2025-07-02 06:41:18.426
2025-07-02 06:41:18.426 # pump out diffs from before the synch point
2025-07-02 06:41:18.426 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.426
2025-07-02 06:41:18.426 # do intraline marking on the synch pair
2025-07-02 06:41:18.426 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.426 if eqi is None:
2025-07-02 06:41:18.427 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.427 atags = btags = ""
2025-07-02 06:41:18.427 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.427 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.427 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.427 if tag == 'replace':
2025-07-02 06:41:18.427 atags += '^' * la
2025-07-02 06:41:18.427 btags += '^' * lb
2025-07-02 06:41:18.427 elif tag == 'delete':
2025-07-02 06:41:18.427 atags += '-' * la
2025-07-02 06:41:18.427 elif tag == 'insert':
2025-07-02 06:41:18.427 btags += '+' * lb
2025-07-02 06:41:18.427 elif tag == 'equal':
2025-07-02 06:41:18.427 atags += ' ' * la
2025-07-02 06:41:18.427 btags += ' ' * lb
2025-07-02 06:41:18.427 else:
2025-07-02 06:41:18.427 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.427 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.427 else:
2025-07-02 06:41:18.427 # the synch pair is identical
2025-07-02 06:41:18.428 yield ' ' + aelt
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428 # pump out diffs from after the synch point
2025-07-02 06:41:18.428 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.428 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.428 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.428 alo = 397, ahi = 1101
2025-07-02 06:41:18.428 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.428 blo = 397, bhi = 1101
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.428 g = []
2025-07-02 06:41:18.428 if alo < ahi:
2025-07-02 06:41:18.428 if blo < bhi:
2025-07-02 06:41:18.428 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.428 else:
2025-07-02 06:41:18.429 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.429 elif blo < bhi:
2025-07-02 06:41:18.429 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 > yield from g
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.429 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.429 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.429 alo = 397, ahi = 1101
2025-07-02 06:41:18.429 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.429 blo = 397, bhi = 1101
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.429 r"""
2025-07-02 06:41:18.429 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.429 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.429 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.430 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430 Example:
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430 >>> d = Differ()
2025-07-02 06:41:18.430 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.430 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.430 >>> print(''.join(results), end="")
2025-07-02 06:41:18.430 - abcDefghiJkl
2025-07-02 06:41:18.430 + abcdefGhijkl
2025-07-02 06:41:18.430 """
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.430 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.430 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.430 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.430 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430 # search for the pair that matches best without being identical
2025-07-02 06:41:18.431 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.431 # on junk -- unless we have to)
2025-07-02 06:41:18.431 for j in range(blo, bhi):
2025-07-02 06:41:18.431 bj = b[j]
2025-07-02 06:41:18.431 cruncher.set_seq2(bj)
2025-07-02 06:41:18.431 for i in range(alo, ahi):
2025-07-02 06:41:18.431 ai = a[i]
2025-07-02 06:41:18.431 if ai == bj:
2025-07-02 06:41:18.431 if eqi is None:
2025-07-02 06:41:18.431 eqi, eqj = i, j
2025-07-02 06:41:18.431 continue
2025-07-02 06:41:18.431 cruncher.set_seq1(ai)
2025-07-02 06:41:18.431 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.431 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.431 # compares by a factor of 3.
2025-07-02 06:41:18.431 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.431 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.431 # of the computation is cached by cruncher
2025-07-02 06:41:18.431 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.432 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.432 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.432 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.432 if best_ratio < cutoff:
2025-07-02 06:41:18.432 # no non-identical "pretty close" pair
2025-07-02 06:41:18.432 if eqi is None:
2025-07-02 06:41:18.432 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.432 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.432 return
2025-07-02 06:41:18.432 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.432 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.432 else:
2025-07-02 06:41:18.432 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.432 eqi = None
2025-07-02 06:41:18.432
2025-07-02 06:41:18.432 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.432 # identical
2025-07-02 06:41:18.432
2025-07-02 06:41:18.432 # pump out diffs from before the synch point
2025-07-02 06:41:18.432 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.433
2025-07-02 06:41:18.433 # do intraline marking on the synch pair
2025-07-02 06:41:18.433 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.433 if eqi is None:
2025-07-02 06:41:18.433 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.433 atags = btags = ""
2025-07-02 06:41:18.433 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.433 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.433 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.433 if tag == 'replace':
2025-07-02 06:41:18.433 atags += '^' * la
2025-07-02 06:41:18.433 btags += '^' * lb
2025-07-02 06:41:18.433 elif tag == 'delete':
2025-07-02 06:41:18.433 atags += '-' * la
2025-07-02 06:41:18.433 elif tag == 'insert':
2025-07-02 06:41:18.433 btags += '+' * lb
2025-07-02 06:41:18.433 elif tag == 'equal':
2025-07-02 06:41:18.433 atags += ' ' * la
2025-07-02 06:41:18.433 btags += ' ' * lb
2025-07-02 06:41:18.433 else:
2025-07-02 06:41:18.434 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.434 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.434 else:
2025-07-02 06:41:18.434 # the synch pair is identical
2025-07-02 06:41:18.434 yield ' ' + aelt
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434 # pump out diffs from after the synch point
2025-07-02 06:41:18.434 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.434 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.434 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.434 alo = 400, ahi = 1101
2025-07-02 06:41:18.434 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.434 blo = 400, bhi = 1101
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.435 g = []
2025-07-02 06:41:18.435 if alo < ahi:
2025-07-02 06:41:18.435 if blo < bhi:
2025-07-02 06:41:18.435 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.435 else:
2025-07-02 06:41:18.435 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.435 elif blo < bhi:
2025-07-02 06:41:18.435 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.435
2025-07-02 06:41:18.435 > yield from g
2025-07-02 06:41:18.435
2025-07-02 06:41:18.435 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.435 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.435
2025-07-02 06:41:18.435 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.435 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.435 alo = 400, ahi = 1101
2025-07-02 06:41:18.435 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.436 blo = 400, bhi = 1101
2025-07-02 06:41:18.436
2025-07-02 06:41:18.436 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.436 r"""
2025-07-02 06:41:18.436 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.436 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.436 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.436 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.436
2025-07-02 06:41:18.436 Example:
2025-07-02 06:41:18.436
2025-07-02 06:41:18.436 >>> d = Differ()
2025-07-02 06:41:18.436 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.436 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.436 >>> print(''.join(results), end="")
2025-07-02 06:41:18.436 - abcDefghiJkl
2025-07-02 06:41:18.436 + abcdefGhijkl
2025-07-02 06:41:18.436 """
2025-07-02 06:41:18.437
2025-07-02 06:41:18.437 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.437 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.437 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.437 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.437 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.437
2025-07-02 06:41:18.437 # search for the pair that matches best without being identical
2025-07-02 06:41:18.437 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.437 # on junk -- unless we have to)
2025-07-02 06:41:18.437 for j in range(blo, bhi):
2025-07-02 06:41:18.437 bj = b[j]
2025-07-02 06:41:18.437 cruncher.set_seq2(bj)
2025-07-02 06:41:18.437 for i in range(alo, ahi):
2025-07-02 06:41:18.437 ai = a[i]
2025-07-02 06:41:18.437 if ai == bj:
2025-07-02 06:41:18.437 if eqi is None:
2025-07-02 06:41:18.437 eqi, eqj = i, j
2025-07-02 06:41:18.438 continue
2025-07-02 06:41:18.438 cruncher.set_seq1(ai)
2025-07-02 06:41:18.438 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.438 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.438 # compares by a factor of 3.
2025-07-02 06:41:18.438 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.438 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.438 # of the computation is cached by cruncher
2025-07-02 06:41:18.438 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.438 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.438 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.438 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.438 if best_ratio < cutoff:
2025-07-02 06:41:18.438 # no non-identical "pretty close" pair
2025-07-02 06:41:18.438 if eqi is None:
2025-07-02 06:41:18.438 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.438 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.438 return
2025-07-02 06:41:18.438 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.439 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.439 else:
2025-07-02 06:41:18.439 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.439 eqi = None
2025-07-02 06:41:18.439
2025-07-02 06:41:18.439 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.439 # identical
2025-07-02 06:41:18.439
2025-07-02 06:41:18.439 # pump out diffs from before the synch point
2025-07-02 06:41:18.439 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.439
2025-07-02 06:41:18.439 # do intraline marking on the synch pair
2025-07-02 06:41:18.439 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.439 if eqi is None:
2025-07-02 06:41:18.439 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.439 atags = btags = ""
2025-07-02 06:41:18.439 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.439 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.439 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.440 if tag == 'replace':
2025-07-02 06:41:18.440 atags += '^' * la
2025-07-02 06:41:18.440 btags += '^' * lb
2025-07-02 06:41:18.440 elif tag == 'delete':
2025-07-02 06:41:18.440 atags += '-' * la
2025-07-02 06:41:18.440 elif tag == 'insert':
2025-07-02 06:41:18.440 btags += '+' * lb
2025-07-02 06:41:18.440 elif tag == 'equal':
2025-07-02 06:41:18.440 atags += ' ' * la
2025-07-02 06:41:18.440 btags += ' ' * lb
2025-07-02 06:41:18.440 else:
2025-07-02 06:41:18.440 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.440 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.440 else:
2025-07-02 06:41:18.440 # the synch pair is identical
2025-07-02 06:41:18.440 yield ' ' + aelt
2025-07-02 06:41:18.440
2025-07-02 06:41:18.440 # pump out diffs from after the synch point
2025-07-02 06:41:18.440 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.440
2025-07-02 06:41:18.440 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.441 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.441
2025-07-02 06:41:18.441 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.441 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.441 alo = 401, ahi = 1101
2025-07-02 06:41:18.441 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.441 blo = 401, bhi = 1101
2025-07-02 06:41:18.441
2025-07-02 06:41:18.441 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.441 g = []
2025-07-02 06:41:18.441 if alo < ahi:
2025-07-02 06:41:18.441 if blo < bhi:
2025-07-02 06:41:18.441 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.441 else:
2025-07-02 06:41:18.441 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.441 elif blo < bhi:
2025-07-02 06:41:18.441 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.441
2025-07-02 06:41:18.441 > yield from g
2025-07-02 06:41:18.441
2025-07-02 06:41:18.442 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.442 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.442 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.442 alo = 401, ahi = 1101
2025-07-02 06:41:18.442 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.442 blo = 401, bhi = 1101
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.442 r"""
2025-07-02 06:41:18.442 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.442 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.442 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.442 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442 Example:
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442 >>> d = Differ()
2025-07-02 06:41:18.442 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.443 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.443 >>> print(''.join(results), end="")
2025-07-02 06:41:18.443 - abcDefghiJkl
2025-07-02 06:41:18.443 + abcdefGhijkl
2025-07-02 06:41:18.443 """
2025-07-02 06:41:18.443
2025-07-02 06:41:18.443 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.443 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.443 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.443 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.443 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.443
2025-07-02 06:41:18.443 # search for the pair that matches best without being identical
2025-07-02 06:41:18.443 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.443 # on junk -- unless we have to)
2025-07-02 06:41:18.443 for j in range(blo, bhi):
2025-07-02 06:41:18.443 bj = b[j]
2025-07-02 06:41:18.443 cruncher.set_seq2(bj)
2025-07-02 06:41:18.443 for i in range(alo, ahi):
2025-07-02 06:41:18.443 ai = a[i]
2025-07-02 06:41:18.443 if ai == bj:
2025-07-02 06:41:18.443 if eqi is None:
2025-07-02 06:41:18.444 eqi, eqj = i, j
2025-07-02 06:41:18.444 continue
2025-07-02 06:41:18.444 cruncher.set_seq1(ai)
2025-07-02 06:41:18.444 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.444 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.444 # compares by a factor of 3.
2025-07-02 06:41:18.444 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.444 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.444 # of the computation is cached by cruncher
2025-07-02 06:41:18.444 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.444 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.444 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.444 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.444 if best_ratio < cutoff:
2025-07-02 06:41:18.444 # no non-identical "pretty close" pair
2025-07-02 06:41:18.444 if eqi is None:
2025-07-02 06:41:18.444 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.444 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.444 return
2025-07-02 06:41:18.445 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.445 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.445 else:
2025-07-02 06:41:18.445 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.445 eqi = None
2025-07-02 06:41:18.445
2025-07-02 06:41:18.445 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.445 # identical
2025-07-02 06:41:18.445
2025-07-02 06:41:18.445 # pump out diffs from before the synch point
2025-07-02 06:41:18.445 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.445
2025-07-02 06:41:18.445 # do intraline marking on the synch pair
2025-07-02 06:41:18.445 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.445 if eqi is None:
2025-07-02 06:41:18.445 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.445 atags = btags = ""
2025-07-02 06:41:18.445 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.445 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.445 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.446 if tag == 'replace':
2025-07-02 06:41:18.446 atags += '^' * la
2025-07-02 06:41:18.446 btags += '^' * lb
2025-07-02 06:41:18.446 elif tag == 'delete':
2025-07-02 06:41:18.446 atags += '-' * la
2025-07-02 06:41:18.446 elif tag == 'insert':
2025-07-02 06:41:18.446 btags += '+' * lb
2025-07-02 06:41:18.446 elif tag == 'equal':
2025-07-02 06:41:18.446 atags += ' ' * la
2025-07-02 06:41:18.446 btags += ' ' * lb
2025-07-02 06:41:18.446 else:
2025-07-02 06:41:18.446 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.446 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.446 else:
2025-07-02 06:41:18.446 # the synch pair is identical
2025-07-02 06:41:18.446 yield ' ' + aelt
2025-07-02 06:41:18.446
2025-07-02 06:41:18.446 # pump out diffs from after the synch point
2025-07-02 06:41:18.446 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.447
2025-07-02 06:41:18.447 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.447 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.447
2025-07-02 06:41:18.447 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.447 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.447 alo = 402, ahi = 1101
2025-07-02 06:41:18.447 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.447 blo = 402, bhi = 1101
2025-07-02 06:41:18.447
2025-07-02 06:41:18.447 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.447 g = []
2025-07-02 06:41:18.447 if alo < ahi:
2025-07-02 06:41:18.447 if blo < bhi:
2025-07-02 06:41:18.447 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.447 else:
2025-07-02 06:41:18.447 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.447 elif blo < bhi:
2025-07-02 06:41:18.447 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 > yield from g
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.448 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.448 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.448 alo = 402, ahi = 1101
2025-07-02 06:41:18.448 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.448 blo = 402, bhi = 1101
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.448 r"""
2025-07-02 06:41:18.448 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.448 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.448 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.448 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 Example:
2025-07-02 06:41:18.449
2025-07-02 06:41:18.449 >>> d = Differ()
2025-07-02 06:41:18.449 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.449 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.449 >>> print(''.join(results), end="")
2025-07-02 06:41:18.449 - abcDefghiJkl
2025-07-02 06:41:18.449 + abcdefGhijkl
2025-07-02 06:41:18.449 """
2025-07-02 06:41:18.449
2025-07-02 06:41:18.449 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.449 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.449 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.449 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.449 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.449
2025-07-02 06:41:18.449 # search for the pair that matches best without being identical
2025-07-02 06:41:18.449 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.450 # on junk -- unless we have to)
2025-07-02 06:41:18.450 for j in range(blo, bhi):
2025-07-02 06:41:18.450 bj = b[j]
2025-07-02 06:41:18.450 cruncher.set_seq2(bj)
2025-07-02 06:41:18.450 for i in range(alo, ahi):
2025-07-02 06:41:18.450 ai = a[i]
2025-07-02 06:41:18.450 if ai == bj:
2025-07-02 06:41:18.450 if eqi is None:
2025-07-02 06:41:18.450 eqi, eqj = i, j
2025-07-02 06:41:18.450 continue
2025-07-02 06:41:18.450 cruncher.set_seq1(ai)
2025-07-02 06:41:18.450 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.450 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.450 # compares by a factor of 3.
2025-07-02 06:41:18.450 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.450 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.450 # of the computation is cached by cruncher
2025-07-02 06:41:18.450 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.450 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.450 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.451 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.451 if best_ratio < cutoff:
2025-07-02 06:41:18.451 # no non-identical "pretty close" pair
2025-07-02 06:41:18.451 if eqi is None:
2025-07-02 06:41:18.451 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.451 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.451 return
2025-07-02 06:41:18.451 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.451 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.451 else:
2025-07-02 06:41:18.451 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.451 eqi = None
2025-07-02 06:41:18.451
2025-07-02 06:41:18.451 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.451 # identical
2025-07-02 06:41:18.451
2025-07-02 06:41:18.451 # pump out diffs from before the synch point
2025-07-02 06:41:18.451 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.452
2025-07-02 06:41:18.452 # do intraline marking on the synch pair
2025-07-02 06:41:18.452 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.452 if eqi is None:
2025-07-02 06:41:18.452 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.452 atags = btags = ""
2025-07-02 06:41:18.452 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.452 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.452 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.452 if tag == 'replace':
2025-07-02 06:41:18.452 atags += '^' * la
2025-07-02 06:41:18.452 btags += '^' * lb
2025-07-02 06:41:18.452 elif tag == 'delete':
2025-07-02 06:41:18.452 atags += '-' * la
2025-07-02 06:41:18.452 elif tag == 'insert':
2025-07-02 06:41:18.452 btags += '+' * lb
2025-07-02 06:41:18.452 elif tag == 'equal':
2025-07-02 06:41:18.452 atags += ' ' * la
2025-07-02 06:41:18.452 btags += ' ' * lb
2025-07-02 06:41:18.453 else:
2025-07-02 06:41:18.453 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.453 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.453 else:
2025-07-02 06:41:18.453 # the synch pair is identical
2025-07-02 06:41:18.453 yield ' ' + aelt
2025-07-02 06:41:18.453
2025-07-02 06:41:18.453 # pump out diffs from after the synch point
2025-07-02 06:41:18.453 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.453
2025-07-02 06:41:18.453 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.453 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.453
2025-07-02 06:41:18.453 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.453 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.453 alo = 403, ahi = 1101
2025-07-02 06:41:18.453 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.453 blo = 403, bhi = 1101
2025-07-02 06:41:18.453
2025-07-02 06:41:18.454 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.454 g = []
2025-07-02 06:41:18.454 if alo < ahi:
2025-07-02 06:41:18.454 if blo < bhi:
2025-07-02 06:41:18.454 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.454 else:
2025-07-02 06:41:18.454 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.454 elif blo < bhi:
2025-07-02 06:41:18.454 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.454
2025-07-02 06:41:18.454 > yield from g
2025-07-02 06:41:18.454
2025-07-02 06:41:18.454 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.454 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.454
2025-07-02 06:41:18.454 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.454 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.454 alo = 403, ahi = 1101
2025-07-02 06:41:18.454 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.455 blo = 403, bhi = 1101
2025-07-02 06:41:18.455
2025-07-02 06:41:18.455 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.455 r"""
2025-07-02 06:41:18.455 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.455 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.455 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.455 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.455
2025-07-02 06:41:18.455 Example:
2025-07-02 06:41:18.455
2025-07-02 06:41:18.455 >>> d = Differ()
2025-07-02 06:41:18.455 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.455 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.455 >>> print(''.join(results), end="")
2025-07-02 06:41:18.455 - abcDefghiJkl
2025-07-02 06:41:18.455 + abcdefGhijkl
2025-07-02 06:41:18.456 """
2025-07-02 06:41:18.456
2025-07-02 06:41:18.456 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.456 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.456 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.456 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.456 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.456
2025-07-02 06:41:18.456 # search for the pair that matches best without being identical
2025-07-02 06:41:18.456 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.456 # on junk -- unless we have to)
2025-07-02 06:41:18.456 for j in range(blo, bhi):
2025-07-02 06:41:18.456 bj = b[j]
2025-07-02 06:41:18.456 cruncher.set_seq2(bj)
2025-07-02 06:41:18.456 for i in range(alo, ahi):
2025-07-02 06:41:18.456 ai = a[i]
2025-07-02 06:41:18.456 if ai == bj:
2025-07-02 06:41:18.456 if eqi is None:
2025-07-02 06:41:18.457 eqi, eqj = i, j
2025-07-02 06:41:18.457 continue
2025-07-02 06:41:18.457 cruncher.set_seq1(ai)
2025-07-02 06:41:18.457 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.457 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.457 # compares by a factor of 3.
2025-07-02 06:41:18.457 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.457 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.457 # of the computation is cached by cruncher
2025-07-02 06:41:18.457 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.457 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.457 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.457 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.457 if best_ratio < cutoff:
2025-07-02 06:41:18.457 # no non-identical "pretty close" pair
2025-07-02 06:41:18.457 if eqi is None:
2025-07-02 06:41:18.457 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.457 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.457 return
2025-07-02 06:41:18.458 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.458 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.458 else:
2025-07-02 06:41:18.458 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.458 eqi = None
2025-07-02 06:41:18.458
2025-07-02 06:41:18.458 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.458 # identical
2025-07-02 06:41:18.458
2025-07-02 06:41:18.458 # pump out diffs from before the synch point
2025-07-02 06:41:18.458 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.458
2025-07-02 06:41:18.458 # do intraline marking on the synch pair
2025-07-02 06:41:18.458 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.458 if eqi is None:
2025-07-02 06:41:18.458 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.458 atags = btags = ""
2025-07-02 06:41:18.458 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.458 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.459 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.459 if tag == 'replace':
2025-07-02 06:41:18.459 atags += '^' * la
2025-07-02 06:41:18.459 btags += '^' * lb
2025-07-02 06:41:18.459 elif tag == 'delete':
2025-07-02 06:41:18.459 atags += '-' * la
2025-07-02 06:41:18.459 elif tag == 'insert':
2025-07-02 06:41:18.459 btags += '+' * lb
2025-07-02 06:41:18.459 elif tag == 'equal':
2025-07-02 06:41:18.459 atags += ' ' * la
2025-07-02 06:41:18.459 btags += ' ' * lb
2025-07-02 06:41:18.459 else:
2025-07-02 06:41:18.459 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.459 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.459 else:
2025-07-02 06:41:18.459 # the synch pair is identical
2025-07-02 06:41:18.459 yield ' ' + aelt
2025-07-02 06:41:18.459
2025-07-02 06:41:18.459 # pump out diffs from after the synch point
2025-07-02 06:41:18.459 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.460
2025-07-02 06:41:18.460 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.460 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.460
2025-07-02 06:41:18.460 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.460 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.460 alo = 404, ahi = 1101
2025-07-02 06:41:18.460 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.460 blo = 404, bhi = 1101
2025-07-02 06:41:18.460
2025-07-02 06:41:18.460 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.460 g = []
2025-07-02 06:41:18.460 if alo < ahi:
2025-07-02 06:41:18.460 if blo < bhi:
2025-07-02 06:41:18.460 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.460 else:
2025-07-02 06:41:18.460 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.460 elif blo < bhi:
2025-07-02 06:41:18.461 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 > yield from g
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.461 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.461 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.461 alo = 404, ahi = 1101
2025-07-02 06:41:18.461 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.461 blo = 404, bhi = 1101
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.461 r"""
2025-07-02 06:41:18.461 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.461 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.461 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.461 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.462
2025-07-02 06:41:18.462 Example:
2025-07-02 06:41:18.462
2025-07-02 06:41:18.462 >>> d = Differ()
2025-07-02 06:41:18.462 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.462 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.462 >>> print(''.join(results), end="")
2025-07-02 06:41:18.462 - abcDefghiJkl
2025-07-02 06:41:18.462 + abcdefGhijkl
2025-07-02 06:41:18.462 """
2025-07-02 06:41:18.462
2025-07-02 06:41:18.462 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.462 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.462 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.462 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.462 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.462
2025-07-02 06:41:18.463 # search for the pair that matches best without being identical
2025-07-02 06:41:18.463 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.463 # on junk -- unless we have to)
2025-07-02 06:41:18.463 for j in range(blo, bhi):
2025-07-02 06:41:18.463 bj = b[j]
2025-07-02 06:41:18.463 cruncher.set_seq2(bj)
2025-07-02 06:41:18.463 for i in range(alo, ahi):
2025-07-02 06:41:18.463 ai = a[i]
2025-07-02 06:41:18.463 if ai == bj:
2025-07-02 06:41:18.463 if eqi is None:
2025-07-02 06:41:18.463 eqi, eqj = i, j
2025-07-02 06:41:18.463 continue
2025-07-02 06:41:18.463 cruncher.set_seq1(ai)
2025-07-02 06:41:18.463 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.463 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.463 # compares by a factor of 3.
2025-07-02 06:41:18.463 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.463 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.463 # of the computation is cached by cruncher
2025-07-02 06:41:18.464 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.464 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.464 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.464 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.464 if best_ratio < cutoff:
2025-07-02 06:41:18.464 # no non-identical "pretty close" pair
2025-07-02 06:41:18.464 if eqi is None:
2025-07-02 06:41:18.464 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.464 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.464 return
2025-07-02 06:41:18.464 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.464 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.464 else:
2025-07-02 06:41:18.464 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.464 eqi = None
2025-07-02 06:41:18.464
2025-07-02 06:41:18.464 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.464 # identical
2025-07-02 06:41:18.464
2025-07-02 06:41:18.465 # pump out diffs from before the synch point
2025-07-02 06:41:18.465 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.465
2025-07-02 06:41:18.465 # do intraline marking on the synch pair
2025-07-02 06:41:18.465 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.465 if eqi is None:
2025-07-02 06:41:18.465 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.465 atags = btags = ""
2025-07-02 06:41:18.465 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.465 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.465 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.465 if tag == 'replace':
2025-07-02 06:41:18.465 atags += '^' * la
2025-07-02 06:41:18.465 btags += '^' * lb
2025-07-02 06:41:18.465 elif tag == 'delete':
2025-07-02 06:41:18.465 atags += '-' * la
2025-07-02 06:41:18.465 elif tag == 'insert':
2025-07-02 06:41:18.465 btags += '+' * lb
2025-07-02 06:41:18.465 elif tag == 'equal':
2025-07-02 06:41:18.466 atags += ' ' * la
2025-07-02 06:41:18.466 btags += ' ' * lb
2025-07-02 06:41:18.466 else:
2025-07-02 06:41:18.466 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.466 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.466 else:
2025-07-02 06:41:18.466 # the synch pair is identical
2025-07-02 06:41:18.466 yield ' ' + aelt
2025-07-02 06:41:18.466
2025-07-02 06:41:18.466 # pump out diffs from after the synch point
2025-07-02 06:41:18.466 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.466
2025-07-02 06:41:18.466 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.466 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.466
2025-07-02 06:41:18.466 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.466 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.466 alo = 405, ahi = 1101
2025-07-02 06:41:18.466 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.467 blo = 405, bhi = 1101
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.467 g = []
2025-07-02 06:41:18.467 if alo < ahi:
2025-07-02 06:41:18.467 if blo < bhi:
2025-07-02 06:41:18.467 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.467 else:
2025-07-02 06:41:18.467 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.467 elif blo < bhi:
2025-07-02 06:41:18.467 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 > yield from g
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.467 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.468 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.468 alo = 405, ahi = 1101
2025-07-02 06:41:18.468 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.468 blo = 405, bhi = 1101
2025-07-02 06:41:18.468
2025-07-02 06:41:18.468 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.468 r"""
2025-07-02 06:41:18.468 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.468 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.468 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.468 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.468
2025-07-02 06:41:18.468 Example:
2025-07-02 06:41:18.468
2025-07-02 06:41:18.468 >>> d = Differ()
2025-07-02 06:41:18.468 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.468 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.468 >>> print(''.join(results), end="")
2025-07-02 06:41:18.468 - abcDefghiJkl
2025-07-02 06:41:18.469 + abcdefGhijkl
2025-07-02 06:41:18.469 """
2025-07-02 06:41:18.469
2025-07-02 06:41:18.469 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.469 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.469 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.469 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.469 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.469
2025-07-02 06:41:18.469 # search for the pair that matches best without being identical
2025-07-02 06:41:18.469 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.469 # on junk -- unless we have to)
2025-07-02 06:41:18.469 for j in range(blo, bhi):
2025-07-02 06:41:18.469 bj = b[j]
2025-07-02 06:41:18.469 cruncher.set_seq2(bj)
2025-07-02 06:41:18.469 for i in range(alo, ahi):
2025-07-02 06:41:18.469 ai = a[i]
2025-07-02 06:41:18.470 if ai == bj:
2025-07-02 06:41:18.470 if eqi is None:
2025-07-02 06:41:18.470 eqi, eqj = i, j
2025-07-02 06:41:18.470 continue
2025-07-02 06:41:18.470 cruncher.set_seq1(ai)
2025-07-02 06:41:18.470 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.470 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.470 # compares by a factor of 3.
2025-07-02 06:41:18.470 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.470 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.470 # of the computation is cached by cruncher
2025-07-02 06:41:18.470 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.470 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.470 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.470 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.470 if best_ratio < cutoff:
2025-07-02 06:41:18.470 # no non-identical "pretty close" pair
2025-07-02 06:41:18.470 if eqi is None:
2025-07-02 06:41:18.471 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.471 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.471 return
2025-07-02 06:41:18.471 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.471 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.471 else:
2025-07-02 06:41:18.471 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.471 eqi = None
2025-07-02 06:41:18.471
2025-07-02 06:41:18.471 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.471 # identical
2025-07-02 06:41:18.471
2025-07-02 06:41:18.471 # pump out diffs from before the synch point
2025-07-02 06:41:18.471 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.471
2025-07-02 06:41:18.471 # do intraline marking on the synch pair
2025-07-02 06:41:18.471 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.471 if eqi is None:
2025-07-02 06:41:18.471 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.472 atags = btags = ""
2025-07-02 06:41:18.472 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.472 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.472 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.472 if tag == 'replace':
2025-07-02 06:41:18.472 atags += '^' * la
2025-07-02 06:41:18.472 btags += '^' * lb
2025-07-02 06:41:18.472 elif tag == 'delete':
2025-07-02 06:41:18.472 atags += '-' * la
2025-07-02 06:41:18.472 elif tag == 'insert':
2025-07-02 06:41:18.472 btags += '+' * lb
2025-07-02 06:41:18.472 elif tag == 'equal':
2025-07-02 06:41:18.472 atags += ' ' * la
2025-07-02 06:41:18.472 btags += ' ' * lb
2025-07-02 06:41:18.472 else:
2025-07-02 06:41:18.472 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.472 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.472 else:
2025-07-02 06:41:18.472 # the synch pair is identical
2025-07-02 06:41:18.473 yield ' ' + aelt
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473 # pump out diffs from after the synch point
2025-07-02 06:41:18.473 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.473 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.473 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.473 alo = 406, ahi = 1101
2025-07-02 06:41:18.473 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.473 blo = 406, bhi = 1101
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.473 g = []
2025-07-02 06:41:18.473 if alo < ahi:
2025-07-02 06:41:18.473 if blo < bhi:
2025-07-02 06:41:18.473 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.474 else:
2025-07-02 06:41:18.474 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.474 elif blo < bhi:
2025-07-02 06:41:18.474 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 > yield from g
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.474 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.474 alo = 406, ahi = 1101
2025-07-02 06:41:18.474 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.474 blo = 406, bhi = 1101
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.474 r"""
2025-07-02 06:41:18.474 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.475 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.475 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.475 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.475
2025-07-02 06:41:18.475 Example:
2025-07-02 06:41:18.475
2025-07-02 06:41:18.475 >>> d = Differ()
2025-07-02 06:41:18.475 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.475 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.475 >>> print(''.join(results), end="")
2025-07-02 06:41:18.475 - abcDefghiJkl
2025-07-02 06:41:18.475 + abcdefGhijkl
2025-07-02 06:41:18.475 """
2025-07-02 06:41:18.475
2025-07-02 06:41:18.475 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.475 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.475 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.476 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.476 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.476
2025-07-02 06:41:18.476 # search for the pair that matches best without being identical
2025-07-02 06:41:18.476 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.476 # on junk -- unless we have to)
2025-07-02 06:41:18.476 for j in range(blo, bhi):
2025-07-02 06:41:18.476 bj = b[j]
2025-07-02 06:41:18.476 cruncher.set_seq2(bj)
2025-07-02 06:41:18.476 for i in range(alo, ahi):
2025-07-02 06:41:18.476 ai = a[i]
2025-07-02 06:41:18.476 if ai == bj:
2025-07-02 06:41:18.476 if eqi is None:
2025-07-02 06:41:18.476 eqi, eqj = i, j
2025-07-02 06:41:18.476 continue
2025-07-02 06:41:18.476 cruncher.set_seq1(ai)
2025-07-02 06:41:18.476 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.476 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.476 # compares by a factor of 3.
2025-07-02 06:41:18.477 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.477 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.477 # of the computation is cached by cruncher
2025-07-02 06:41:18.477 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.477 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.477 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.477 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.477 if best_ratio < cutoff:
2025-07-02 06:41:18.477 # no non-identical "pretty close" pair
2025-07-02 06:41:18.477 if eqi is None:
2025-07-02 06:41:18.477 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.477 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.477 return
2025-07-02 06:41:18.477 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.477 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.477 else:
2025-07-02 06:41:18.477 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.477 eqi = None
2025-07-02 06:41:18.477
2025-07-02 06:41:18.478 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.478 # identical
2025-07-02 06:41:18.478
2025-07-02 06:41:18.478 # pump out diffs from before the synch point
2025-07-02 06:41:18.478 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.478
2025-07-02 06:41:18.478 # do intraline marking on the synch pair
2025-07-02 06:41:18.478 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.478 if eqi is None:
2025-07-02 06:41:18.478 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.478 atags = btags = ""
2025-07-02 06:41:18.478 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.478 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.478 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.478 if tag == 'replace':
2025-07-02 06:41:18.478 atags += '^' * la
2025-07-02 06:41:18.478 btags += '^' * lb
2025-07-02 06:41:18.478 elif tag == 'delete':
2025-07-02 06:41:18.478 atags += '-' * la
2025-07-02 06:41:18.479 elif tag == 'insert':
2025-07-02 06:41:18.479 btags += '+' * lb
2025-07-02 06:41:18.479 elif tag == 'equal':
2025-07-02 06:41:18.479 atags += ' ' * la
2025-07-02 06:41:18.479 btags += ' ' * lb
2025-07-02 06:41:18.479 else:
2025-07-02 06:41:18.479 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.479 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.479 else:
2025-07-02 06:41:18.479 # the synch pair is identical
2025-07-02 06:41:18.479 yield ' ' + aelt
2025-07-02 06:41:18.479
2025-07-02 06:41:18.479 # pump out diffs from after the synch point
2025-07-02 06:41:18.479 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.479
2025-07-02 06:41:18.479 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.479 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.479
2025-07-02 06:41:18.479 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.480 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.480 alo = 407, ahi = 1101
2025-07-02 06:41:18.480 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.480 blo = 407, bhi = 1101
2025-07-02 06:41:18.480
2025-07-02 06:41:18.480 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.480 g = []
2025-07-02 06:41:18.480 if alo < ahi:
2025-07-02 06:41:18.480 if blo < bhi:
2025-07-02 06:41:18.480 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.480 else:
2025-07-02 06:41:18.480 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.480 elif blo < bhi:
2025-07-02 06:41:18.480 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.480
2025-07-02 06:41:18.480 > yield from g
2025-07-02 06:41:18.480
2025-07-02 06:41:18.480 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.481 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.481 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.481 alo = 407, ahi = 1101
2025-07-02 06:41:18.481 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.481 blo = 407, bhi = 1101
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.481 r"""
2025-07-02 06:41:18.481 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.481 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.481 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.481 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481 Example:
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481 >>> d = Differ()
2025-07-02 06:41:18.481 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.482 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.482 >>> print(''.join(results), end="")
2025-07-02 06:41:18.482 - abcDefghiJkl
2025-07-02 06:41:18.482 + abcdefGhijkl
2025-07-02 06:41:18.482 """
2025-07-02 06:41:18.482
2025-07-02 06:41:18.482 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.482 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.482 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.482 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.482 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.482
2025-07-02 06:41:18.482 # search for the pair that matches best without being identical
2025-07-02 06:41:18.482 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.482 # on junk -- unless we have to)
2025-07-02 06:41:18.482 for j in range(blo, bhi):
2025-07-02 06:41:18.482 bj = b[j]
2025-07-02 06:41:18.483 cruncher.set_seq2(bj)
2025-07-02 06:41:18.483 for i in range(alo, ahi):
2025-07-02 06:41:18.483 ai = a[i]
2025-07-02 06:41:18.483 if ai == bj:
2025-07-02 06:41:18.483 if eqi is None:
2025-07-02 06:41:18.483 eqi, eqj = i, j
2025-07-02 06:41:18.483 continue
2025-07-02 06:41:18.483 cruncher.set_seq1(ai)
2025-07-02 06:41:18.483 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.483 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.483 # compares by a factor of 3.
2025-07-02 06:41:18.483 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.483 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.483 # of the computation is cached by cruncher
2025-07-02 06:41:18.483 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.483 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.483 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.483 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.483 if best_ratio < cutoff:
2025-07-02 06:41:18.484 # no non-identical "pretty close" pair
2025-07-02 06:41:18.484 if eqi is None:
2025-07-02 06:41:18.484 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.484 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.484 return
2025-07-02 06:41:18.484 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.484 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.484 else:
2025-07-02 06:41:18.484 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.484 eqi = None
2025-07-02 06:41:18.484
2025-07-02 06:41:18.484 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.484 # identical
2025-07-02 06:41:18.484
2025-07-02 06:41:18.484 # pump out diffs from before the synch point
2025-07-02 06:41:18.484 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.484
2025-07-02 06:41:18.484 # do intraline marking on the synch pair
2025-07-02 06:41:18.484 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.485 if eqi is None:
2025-07-02 06:41:18.485 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.485 atags = btags = ""
2025-07-02 06:41:18.485 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.485 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.485 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.485 if tag == 'replace':
2025-07-02 06:41:18.485 atags += '^' * la
2025-07-02 06:41:18.485 btags += '^' * lb
2025-07-02 06:41:18.485 elif tag == 'delete':
2025-07-02 06:41:18.485 atags += '-' * la
2025-07-02 06:41:18.485 elif tag == 'insert':
2025-07-02 06:41:18.485 btags += '+' * lb
2025-07-02 06:41:18.485 elif tag == 'equal':
2025-07-02 06:41:18.485 atags += ' ' * la
2025-07-02 06:41:18.485 btags += ' ' * lb
2025-07-02 06:41:18.485 else:
2025-07-02 06:41:18.485 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.485 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.486 else:
2025-07-02 06:41:18.486 # the synch pair is identical
2025-07-02 06:41:18.486 yield ' ' + aelt
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486 # pump out diffs from after the synch point
2025-07-02 06:41:18.486 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.486 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.486 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.486 alo = 408, ahi = 1101
2025-07-02 06:41:18.486 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.486 blo = 408, bhi = 1101
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.486 g = []
2025-07-02 06:41:18.486 if alo < ahi:
2025-07-02 06:41:18.487 if blo < bhi:
2025-07-02 06:41:18.487 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.487 else:
2025-07-02 06:41:18.487 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.487 elif blo < bhi:
2025-07-02 06:41:18.487 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 > yield from g
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.487 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.487 alo = 408, ahi = 1101
2025-07-02 06:41:18.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.487 blo = 408, bhi = 1101
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.488 r"""
2025-07-02 06:41:18.488 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.488 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.488 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.488 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.488
2025-07-02 06:41:18.488 Example:
2025-07-02 06:41:18.488
2025-07-02 06:41:18.488 >>> d = Differ()
2025-07-02 06:41:18.488 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.488 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.488 >>> print(''.join(results), end="")
2025-07-02 06:41:18.488 - abcDefghiJkl
2025-07-02 06:41:18.488 + abcdefGhijkl
2025-07-02 06:41:18.488 """
2025-07-02 06:41:18.488
2025-07-02 06:41:18.489 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.489 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.489 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.489 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.489 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.489
2025-07-02 06:41:18.489 # search for the pair that matches best without being identical
2025-07-02 06:41:18.489 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.489 # on junk -- unless we have to)
2025-07-02 06:41:18.489 for j in range(blo, bhi):
2025-07-02 06:41:18.489 bj = b[j]
2025-07-02 06:41:18.489 cruncher.set_seq2(bj)
2025-07-02 06:41:18.489 for i in range(alo, ahi):
2025-07-02 06:41:18.489 ai = a[i]
2025-07-02 06:41:18.489 if ai == bj:
2025-07-02 06:41:18.489 if eqi is None:
2025-07-02 06:41:18.489 eqi, eqj = i, j
2025-07-02 06:41:18.489 continue
2025-07-02 06:41:18.489 cruncher.set_seq1(ai)
2025-07-02 06:41:18.490 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.490 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.490 # compares by a factor of 3.
2025-07-02 06:41:18.490 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.490 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.490 # of the computation is cached by cruncher
2025-07-02 06:41:18.490 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.490 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.490 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.490 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.490 if best_ratio < cutoff:
2025-07-02 06:41:18.490 # no non-identical "pretty close" pair
2025-07-02 06:41:18.490 if eqi is None:
2025-07-02 06:41:18.490 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.490 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.490 return
2025-07-02 06:41:18.490 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.490 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.490 else:
2025-07-02 06:41:18.491 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.491 eqi = None
2025-07-02 06:41:18.491
2025-07-02 06:41:18.491 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.491 # identical
2025-07-02 06:41:18.491
2025-07-02 06:41:18.491 # pump out diffs from before the synch point
2025-07-02 06:41:18.491 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.491
2025-07-02 06:41:18.491 # do intraline marking on the synch pair
2025-07-02 06:41:18.491 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.491 if eqi is None:
2025-07-02 06:41:18.491 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.491 atags = btags = ""
2025-07-02 06:41:18.491 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.491 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.491 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.491 if tag == 'replace':
2025-07-02 06:41:18.491 atags += '^' * la
2025-07-02 06:41:18.492 btags += '^' * lb
2025-07-02 06:41:18.492 elif tag == 'delete':
2025-07-02 06:41:18.492 atags += '-' * la
2025-07-02 06:41:18.492 elif tag == 'insert':
2025-07-02 06:41:18.492 btags += '+' * lb
2025-07-02 06:41:18.492 elif tag == 'equal':
2025-07-02 06:41:18.492 atags += ' ' * la
2025-07-02 06:41:18.492 btags += ' ' * lb
2025-07-02 06:41:18.492 else:
2025-07-02 06:41:18.492 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.492 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.492 else:
2025-07-02 06:41:18.492 # the synch pair is identical
2025-07-02 06:41:18.492 yield ' ' + aelt
2025-07-02 06:41:18.492
2025-07-02 06:41:18.492 # pump out diffs from after the synch point
2025-07-02 06:41:18.492 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.492
2025-07-02 06:41:18.492 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.492 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.493
2025-07-02 06:41:18.493 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.493 alo = 409, ahi = 1101
2025-07-02 06:41:18.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.493 blo = 409, bhi = 1101
2025-07-02 06:41:18.493
2025-07-02 06:41:18.493 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.493 g = []
2025-07-02 06:41:18.493 if alo < ahi:
2025-07-02 06:41:18.493 if blo < bhi:
2025-07-02 06:41:18.493 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.493 else:
2025-07-02 06:41:18.493 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.493 elif blo < bhi:
2025-07-02 06:41:18.493 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.493
2025-07-02 06:41:18.493 > yield from g
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.494 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.494 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.494 alo = 409, ahi = 1101
2025-07-02 06:41:18.494 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.494 blo = 409, bhi = 1101
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.494 r"""
2025-07-02 06:41:18.494 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.494 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.494 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.494 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494 Example:
2025-07-02 06:41:18.494
2025-07-02 06:41:18.495 >>> d = Differ()
2025-07-02 06:41:18.495 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.495 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.495 >>> print(''.join(results), end="")
2025-07-02 06:41:18.495 - abcDefghiJkl
2025-07-02 06:41:18.495 + abcdefGhijkl
2025-07-02 06:41:18.495 """
2025-07-02 06:41:18.495
2025-07-02 06:41:18.495 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.495 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.495 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.495 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.495 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.495
2025-07-02 06:41:18.495 # search for the pair that matches best without being identical
2025-07-02 06:41:18.495 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.496 # on junk -- unless we have to)
2025-07-02 06:41:18.496 for j in range(blo, bhi):
2025-07-02 06:41:18.496 bj = b[j]
2025-07-02 06:41:18.496 cruncher.set_seq2(bj)
2025-07-02 06:41:18.496 for i in range(alo, ahi):
2025-07-02 06:41:18.496 ai = a[i]
2025-07-02 06:41:18.496 if ai == bj:
2025-07-02 06:41:18.496 if eqi is None:
2025-07-02 06:41:18.496 eqi, eqj = i, j
2025-07-02 06:41:18.496 continue
2025-07-02 06:41:18.496 cruncher.set_seq1(ai)
2025-07-02 06:41:18.496 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.496 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.496 # compares by a factor of 3.
2025-07-02 06:41:18.496 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.496 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.496 # of the computation is cached by cruncher
2025-07-02 06:41:18.496 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.496 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.496 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.497 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.497 if best_ratio < cutoff:
2025-07-02 06:41:18.497 # no non-identical "pretty close" pair
2025-07-02 06:41:18.497 if eqi is None:
2025-07-02 06:41:18.497 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.497 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.497 return
2025-07-02 06:41:18.497 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.497 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.497 else:
2025-07-02 06:41:18.497 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.497 eqi = None
2025-07-02 06:41:18.497
2025-07-02 06:41:18.497 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.497 # identical
2025-07-02 06:41:18.497
2025-07-02 06:41:18.497 # pump out diffs from before the synch point
2025-07-02 06:41:18.498 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.498
2025-07-02 06:41:18.498 # do intraline marking on the synch pair
2025-07-02 06:41:18.498 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.498 if eqi is None:
2025-07-02 06:41:18.498 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.498 atags = btags = ""
2025-07-02 06:41:18.498 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.498 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.498 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.498 if tag == 'replace':
2025-07-02 06:41:18.498 atags += '^' * la
2025-07-02 06:41:18.498 btags += '^' * lb
2025-07-02 06:41:18.498 elif tag == 'delete':
2025-07-02 06:41:18.498 atags += '-' * la
2025-07-02 06:41:18.498 elif tag == 'insert':
2025-07-02 06:41:18.498 btags += '+' * lb
2025-07-02 06:41:18.498 elif tag == 'equal':
2025-07-02 06:41:18.498 atags += ' ' * la
2025-07-02 06:41:18.499 btags += ' ' * lb
2025-07-02 06:41:18.499 else:
2025-07-02 06:41:18.499 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.499 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.499 else:
2025-07-02 06:41:18.499 # the synch pair is identical
2025-07-02 06:41:18.499 yield ' ' + aelt
2025-07-02 06:41:18.499
2025-07-02 06:41:18.499 # pump out diffs from after the synch point
2025-07-02 06:41:18.499 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.499
2025-07-02 06:41:18.499 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.499
2025-07-02 06:41:18.499 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.499 alo = 410, ahi = 1101
2025-07-02 06:41:18.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.500 blo = 410, bhi = 1101
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.500 g = []
2025-07-02 06:41:18.500 if alo < ahi:
2025-07-02 06:41:18.500 if blo < bhi:
2025-07-02 06:41:18.500 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.500 else:
2025-07-02 06:41:18.500 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.500 elif blo < bhi:
2025-07-02 06:41:18.500 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 > yield from g
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.500 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.500 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.501 alo = 410, ahi = 1101
2025-07-02 06:41:18.501 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.501 blo = 410, bhi = 1101
2025-07-02 06:41:18.501
2025-07-02 06:41:18.501 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.501 r"""
2025-07-02 06:41:18.501 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.501 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.501 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.501 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.501
2025-07-02 06:41:18.501 Example:
2025-07-02 06:41:18.501
2025-07-02 06:41:18.501 >>> d = Differ()
2025-07-02 06:41:18.501 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.501 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.501 >>> print(''.join(results), end="")
2025-07-02 06:41:18.501 - abcDefghiJkl
2025-07-02 06:41:18.502 + abcdefGhijkl
2025-07-02 06:41:18.502 """
2025-07-02 06:41:18.502
2025-07-02 06:41:18.502 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.502 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.502 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.502 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.502 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.502
2025-07-02 06:41:18.502 # search for the pair that matches best without being identical
2025-07-02 06:41:18.502 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.502 # on junk -- unless we have to)
2025-07-02 06:41:18.502 for j in range(blo, bhi):
2025-07-02 06:41:18.502 bj = b[j]
2025-07-02 06:41:18.502 cruncher.set_seq2(bj)
2025-07-02 06:41:18.502 for i in range(alo, ahi):
2025-07-02 06:41:18.502 ai = a[i]
2025-07-02 06:41:18.502 if ai == bj:
2025-07-02 06:41:18.503 if eqi is None:
2025-07-02 06:41:18.503 eqi, eqj = i, j
2025-07-02 06:41:18.503 continue
2025-07-02 06:41:18.503 cruncher.set_seq1(ai)
2025-07-02 06:41:18.503 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.503 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.503 # compares by a factor of 3.
2025-07-02 06:41:18.503 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.503 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.503 # of the computation is cached by cruncher
2025-07-02 06:41:18.503 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.503 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.503 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.503 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.503 if best_ratio < cutoff:
2025-07-02 06:41:18.503 # no non-identical "pretty close" pair
2025-07-02 06:41:18.503 if eqi is None:
2025-07-02 06:41:18.503 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.503 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.504 return
2025-07-02 06:41:18.504 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.504 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.504 else:
2025-07-02 06:41:18.504 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.504 eqi = None
2025-07-02 06:41:18.504
2025-07-02 06:41:18.504 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.504 # identical
2025-07-02 06:41:18.504
2025-07-02 06:41:18.504 # pump out diffs from before the synch point
2025-07-02 06:41:18.504 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.504
2025-07-02 06:41:18.504 # do intraline marking on the synch pair
2025-07-02 06:41:18.504 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.504 if eqi is None:
2025-07-02 06:41:18.504 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.504 atags = btags = ""
2025-07-02 06:41:18.504 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.505 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.505 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.505 if tag == 'replace':
2025-07-02 06:41:18.505 atags += '^' * la
2025-07-02 06:41:18.505 btags += '^' * lb
2025-07-02 06:41:18.505 elif tag == 'delete':
2025-07-02 06:41:18.505 atags += '-' * la
2025-07-02 06:41:18.505 elif tag == 'insert':
2025-07-02 06:41:18.505 btags += '+' * lb
2025-07-02 06:41:18.505 elif tag == 'equal':
2025-07-02 06:41:18.505 atags += ' ' * la
2025-07-02 06:41:18.505 btags += ' ' * lb
2025-07-02 06:41:18.505 else:
2025-07-02 06:41:18.505 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.505 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.505 else:
2025-07-02 06:41:18.505 # the synch pair is identical
2025-07-02 06:41:18.505 yield ' ' + aelt
2025-07-02 06:41:18.505
2025-07-02 06:41:18.506 # pump out diffs from after the synch point
2025-07-02 06:41:18.506 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.506
2025-07-02 06:41:18.506 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.506 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.506
2025-07-02 06:41:18.506 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.506 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.506 alo = 411, ahi = 1101
2025-07-02 06:41:18.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.506 blo = 411, bhi = 1101
2025-07-02 06:41:18.506
2025-07-02 06:41:18.506 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.506 g = []
2025-07-02 06:41:18.506 if alo < ahi:
2025-07-02 06:41:18.506 if blo < bhi:
2025-07-02 06:41:18.506 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.506 else:
2025-07-02 06:41:18.507 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.507 elif blo < bhi:
2025-07-02 06:41:18.507 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 > yield from g
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.507 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.507 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.507 alo = 411, ahi = 1101
2025-07-02 06:41:18.507 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.507 blo = 411, bhi = 1101
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.507 r"""
2025-07-02 06:41:18.507 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.507 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.508 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.508 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.508
2025-07-02 06:41:18.508 Example:
2025-07-02 06:41:18.508
2025-07-02 06:41:18.508 >>> d = Differ()
2025-07-02 06:41:18.508 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.508 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.508 >>> print(''.join(results), end="")
2025-07-02 06:41:18.508 - abcDefghiJkl
2025-07-02 06:41:18.508 + abcdefGhijkl
2025-07-02 06:41:18.508 """
2025-07-02 06:41:18.508
2025-07-02 06:41:18.508 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.508 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.508 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.508 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.509 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.509
2025-07-02 06:41:18.509 # search for the pair that matches best without being identical
2025-07-02 06:41:18.509 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.509 # on junk -- unless we have to)
2025-07-02 06:41:18.509 for j in range(blo, bhi):
2025-07-02 06:41:18.509 bj = b[j]
2025-07-02 06:41:18.509 cruncher.set_seq2(bj)
2025-07-02 06:41:18.509 for i in range(alo, ahi):
2025-07-02 06:41:18.509 ai = a[i]
2025-07-02 06:41:18.509 if ai == bj:
2025-07-02 06:41:18.509 if eqi is None:
2025-07-02 06:41:18.509 eqi, eqj = i, j
2025-07-02 06:41:18.509 continue
2025-07-02 06:41:18.509 cruncher.set_seq1(ai)
2025-07-02 06:41:18.509 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.509 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.509 # compares by a factor of 3.
2025-07-02 06:41:18.509 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.510 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.510 # of the computation is cached by cruncher
2025-07-02 06:41:18.510 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.510 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.510 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.510 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.510 if best_ratio < cutoff:
2025-07-02 06:41:18.510 # no non-identical "pretty close" pair
2025-07-02 06:41:18.510 if eqi is None:
2025-07-02 06:41:18.510 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.510 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.510 return
2025-07-02 06:41:18.510 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.510 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.510 else:
2025-07-02 06:41:18.510 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.510 eqi = None
2025-07-02 06:41:18.510
2025-07-02 06:41:18.510 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.511 # identical
2025-07-02 06:41:18.511
2025-07-02 06:41:18.511 # pump out diffs from before the synch point
2025-07-02 06:41:18.511 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.511
2025-07-02 06:41:18.511 # do intraline marking on the synch pair
2025-07-02 06:41:18.511 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.511 if eqi is None:
2025-07-02 06:41:18.511 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.511 atags = btags = ""
2025-07-02 06:41:18.511 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.511 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.511 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.511 if tag == 'replace':
2025-07-02 06:41:18.511 atags += '^' * la
2025-07-02 06:41:18.511 btags += '^' * lb
2025-07-02 06:41:18.511 elif tag == 'delete':
2025-07-02 06:41:18.511 atags += '-' * la
2025-07-02 06:41:18.511 elif tag == 'insert':
2025-07-02 06:41:18.512 btags += '+' * lb
2025-07-02 06:41:18.512 elif tag == 'equal':
2025-07-02 06:41:18.512 atags += ' ' * la
2025-07-02 06:41:18.512 btags += ' ' * lb
2025-07-02 06:41:18.512 else:
2025-07-02 06:41:18.512 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.512 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.512 else:
2025-07-02 06:41:18.512 # the synch pair is identical
2025-07-02 06:41:18.512 yield ' ' + aelt
2025-07-02 06:41:18.512
2025-07-02 06:41:18.512 # pump out diffs from after the synch point
2025-07-02 06:41:18.512 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.512
2025-07-02 06:41:18.512 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.512 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.512
2025-07-02 06:41:18.512 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.512 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.513 alo = 412, ahi = 1101
2025-07-02 06:41:18.513 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.513 blo = 412, bhi = 1101
2025-07-02 06:41:18.513
2025-07-02 06:41:18.513 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.513 g = []
2025-07-02 06:41:18.513 if alo < ahi:
2025-07-02 06:41:18.513 if blo < bhi:
2025-07-02 06:41:18.513 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.513 else:
2025-07-02 06:41:18.513 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.513 elif blo < bhi:
2025-07-02 06:41:18.513 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.513
2025-07-02 06:41:18.513 > yield from g
2025-07-02 06:41:18.513
2025-07-02 06:41:18.513 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.513 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.513
2025-07-02 06:41:18.514 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.514 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.514 alo = 412, ahi = 1101
2025-07-02 06:41:18.514 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.514 blo = 412, bhi = 1101
2025-07-02 06:41:18.514
2025-07-02 06:41:18.514 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.514 r"""
2025-07-02 06:41:18.514 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.514 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.514 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.514 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.514
2025-07-02 06:41:18.514 Example:
2025-07-02 06:41:18.514
2025-07-02 06:41:18.514 >>> d = Differ()
2025-07-02 06:41:18.514 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.514 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.514 >>> print(''.join(results), end="")
2025-07-02 06:41:18.515 - abcDefghiJkl
2025-07-02 06:41:18.515 + abcdefGhijkl
2025-07-02 06:41:18.515 """
2025-07-02 06:41:18.515
2025-07-02 06:41:18.515 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.515 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.515 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.515 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.515 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.515
2025-07-02 06:41:18.515 # search for the pair that matches best without being identical
2025-07-02 06:41:18.515 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.515 # on junk -- unless we have to)
2025-07-02 06:41:18.515 for j in range(blo, bhi):
2025-07-02 06:41:18.515 bj = b[j]
2025-07-02 06:41:18.515 cruncher.set_seq2(bj)
2025-07-02 06:41:18.516 for i in range(alo, ahi):
2025-07-02 06:41:18.516 ai = a[i]
2025-07-02 06:41:18.516 if ai == bj:
2025-07-02 06:41:18.516 if eqi is None:
2025-07-02 06:41:18.516 eqi, eqj = i, j
2025-07-02 06:41:18.516 continue
2025-07-02 06:41:18.516 cruncher.set_seq1(ai)
2025-07-02 06:41:18.516 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.516 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.516 # compares by a factor of 3.
2025-07-02 06:41:18.516 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.516 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.516 # of the computation is cached by cruncher
2025-07-02 06:41:18.516 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.516 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.516 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.516 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.517 if best_ratio < cutoff:
2025-07-02 06:41:18.517 # no non-identical "pretty close" pair
2025-07-02 06:41:18.517 if eqi is None:
2025-07-02 06:41:18.517 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.517 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.517 return
2025-07-02 06:41:18.517 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.517 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.517 else:
2025-07-02 06:41:18.517 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.517 eqi = None
2025-07-02 06:41:18.517
2025-07-02 06:41:18.517 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.517 # identical
2025-07-02 06:41:18.517
2025-07-02 06:41:18.517 # pump out diffs from before the synch point
2025-07-02 06:41:18.517 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.517
2025-07-02 06:41:18.517 # do intraline marking on the synch pair
2025-07-02 06:41:18.518 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.518 if eqi is None:
2025-07-02 06:41:18.518 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.518 atags = btags = ""
2025-07-02 06:41:18.518 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.518 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.518 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.518 if tag == 'replace':
2025-07-02 06:41:18.518 atags += '^' * la
2025-07-02 06:41:18.518 btags += '^' * lb
2025-07-02 06:41:18.518 elif tag == 'delete':
2025-07-02 06:41:18.518 atags += '-' * la
2025-07-02 06:41:18.518 elif tag == 'insert':
2025-07-02 06:41:18.518 btags += '+' * lb
2025-07-02 06:41:18.518 elif tag == 'equal':
2025-07-02 06:41:18.518 atags += ' ' * la
2025-07-02 06:41:18.518 btags += ' ' * lb
2025-07-02 06:41:18.518 else:
2025-07-02 06:41:18.519 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.519 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.519 else:
2025-07-02 06:41:18.519 # the synch pair is identical
2025-07-02 06:41:18.519 yield ' ' + aelt
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519 # pump out diffs from after the synch point
2025-07-02 06:41:18.519 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.519 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.519 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.519 alo = 413, ahi = 1101
2025-07-02 06:41:18.519 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.519 blo = 413, bhi = 1101
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.520 g = []
2025-07-02 06:41:18.520 if alo < ahi:
2025-07-02 06:41:18.520 if blo < bhi:
2025-07-02 06:41:18.520 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.520 else:
2025-07-02 06:41:18.520 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.520 elif blo < bhi:
2025-07-02 06:41:18.520 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.520
2025-07-02 06:41:18.520 > yield from g
2025-07-02 06:41:18.520
2025-07-02 06:41:18.520 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.520 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.520
2025-07-02 06:41:18.520 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.520 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.520 alo = 413, ahi = 1101
2025-07-02 06:41:18.520 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.521 blo = 413, bhi = 1101
2025-07-02 06:41:18.521
2025-07-02 06:41:18.521 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.521 r"""
2025-07-02 06:41:18.521 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.521 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.521 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.521 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.521
2025-07-02 06:41:18.521 Example:
2025-07-02 06:41:18.521
2025-07-02 06:41:18.521 >>> d = Differ()
2025-07-02 06:41:18.521 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.521 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.521 >>> print(''.join(results), end="")
2025-07-02 06:41:18.521 - abcDefghiJkl
2025-07-02 06:41:18.521 + abcdefGhijkl
2025-07-02 06:41:18.521 """
2025-07-02 06:41:18.522
2025-07-02 06:41:18.522 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.522 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.522 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.522 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.522 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.522
2025-07-02 06:41:18.522 # search for the pair that matches best without being identical
2025-07-02 06:41:18.522 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.522 # on junk -- unless we have to)
2025-07-02 06:41:18.522 for j in range(blo, bhi):
2025-07-02 06:41:18.522 bj = b[j]
2025-07-02 06:41:18.522 cruncher.set_seq2(bj)
2025-07-02 06:41:18.522 for i in range(alo, ahi):
2025-07-02 06:41:18.522 ai = a[i]
2025-07-02 06:41:18.522 if ai == bj:
2025-07-02 06:41:18.522 if eqi is None:
2025-07-02 06:41:18.522 eqi, eqj = i, j
2025-07-02 06:41:18.523 continue
2025-07-02 06:41:18.523 cruncher.set_seq1(ai)
2025-07-02 06:41:18.523 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.523 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.523 # compares by a factor of 3.
2025-07-02 06:41:18.523 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.523 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.523 # of the computation is cached by cruncher
2025-07-02 06:41:18.523 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.523 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.523 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.523 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.523 if best_ratio < cutoff:
2025-07-02 06:41:18.523 # no non-identical "pretty close" pair
2025-07-02 06:41:18.523 if eqi is None:
2025-07-02 06:41:18.523 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.523 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.523 return
2025-07-02 06:41:18.523 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.524 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.524 else:
2025-07-02 06:41:18.524 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.524 eqi = None
2025-07-02 06:41:18.524
2025-07-02 06:41:18.524 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.524 # identical
2025-07-02 06:41:18.524
2025-07-02 06:41:18.524 # pump out diffs from before the synch point
2025-07-02 06:41:18.524 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.524
2025-07-02 06:41:18.524 # do intraline marking on the synch pair
2025-07-02 06:41:18.524 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.524 if eqi is None:
2025-07-02 06:41:18.524 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.524 atags = btags = ""
2025-07-02 06:41:18.524 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.524 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.524 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.525 if tag == 'replace':
2025-07-02 06:41:18.525 atags += '^' * la
2025-07-02 06:41:18.525 btags += '^' * lb
2025-07-02 06:41:18.525 elif tag == 'delete':
2025-07-02 06:41:18.525 atags += '-' * la
2025-07-02 06:41:18.525 elif tag == 'insert':
2025-07-02 06:41:18.525 btags += '+' * lb
2025-07-02 06:41:18.525 elif tag == 'equal':
2025-07-02 06:41:18.525 atags += ' ' * la
2025-07-02 06:41:18.525 btags += ' ' * lb
2025-07-02 06:41:18.525 else:
2025-07-02 06:41:18.525 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.525 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.525 else:
2025-07-02 06:41:18.525 # the synch pair is identical
2025-07-02 06:41:18.525 yield ' ' + aelt
2025-07-02 06:41:18.525
2025-07-02 06:41:18.525 # pump out diffs from after the synch point
2025-07-02 06:41:18.525 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.526
2025-07-02 06:41:18.526 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.526 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.526
2025-07-02 06:41:18.526 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.526 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.526 alo = 414, ahi = 1101
2025-07-02 06:41:18.526 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.526 blo = 414, bhi = 1101
2025-07-02 06:41:18.526
2025-07-02 06:41:18.526 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.526 g = []
2025-07-02 06:41:18.526 if alo < ahi:
2025-07-02 06:41:18.526 if blo < bhi:
2025-07-02 06:41:18.526 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.526 else:
2025-07-02 06:41:18.526 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.526 elif blo < bhi:
2025-07-02 06:41:18.527 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 > yield from g
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.527 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.527 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.527 alo = 414, ahi = 1101
2025-07-02 06:41:18.527 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.527 blo = 414, bhi = 1101
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.527 r"""
2025-07-02 06:41:18.527 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.527 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.527 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.527 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.528
2025-07-02 06:41:18.528 Example:
2025-07-02 06:41:18.528
2025-07-02 06:41:18.528 >>> d = Differ()
2025-07-02 06:41:18.528 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.528 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.528 >>> print(''.join(results), end="")
2025-07-02 06:41:18.528 - abcDefghiJkl
2025-07-02 06:41:18.528 + abcdefGhijkl
2025-07-02 06:41:18.528 """
2025-07-02 06:41:18.528
2025-07-02 06:41:18.528 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.528 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.528 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.528 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.528 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.528
2025-07-02 06:41:18.529 # search for the pair that matches best without being identical
2025-07-02 06:41:18.529 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.529 # on junk -- unless we have to)
2025-07-02 06:41:18.529 for j in range(blo, bhi):
2025-07-02 06:41:18.529 bj = b[j]
2025-07-02 06:41:18.529 cruncher.set_seq2(bj)
2025-07-02 06:41:18.529 for i in range(alo, ahi):
2025-07-02 06:41:18.529 ai = a[i]
2025-07-02 06:41:18.529 if ai == bj:
2025-07-02 06:41:18.529 if eqi is None:
2025-07-02 06:41:18.529 eqi, eqj = i, j
2025-07-02 06:41:18.529 continue
2025-07-02 06:41:18.529 cruncher.set_seq1(ai)
2025-07-02 06:41:18.529 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.529 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.529 # compares by a factor of 3.
2025-07-02 06:41:18.529 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.529 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.529 # of the computation is cached by cruncher
2025-07-02 06:41:18.530 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.530 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.530 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.530 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.530 if best_ratio < cutoff:
2025-07-02 06:41:18.530 # no non-identical "pretty close" pair
2025-07-02 06:41:18.530 if eqi is None:
2025-07-02 06:41:18.530 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.530 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.530 return
2025-07-02 06:41:18.530 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.530 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.530 else:
2025-07-02 06:41:18.530 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.530 eqi = None
2025-07-02 06:41:18.530
2025-07-02 06:41:18.530 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.530 # identical
2025-07-02 06:41:18.530
2025-07-02 06:41:18.531 # pump out diffs from before the synch point
2025-07-02 06:41:18.531 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.531
2025-07-02 06:41:18.531 # do intraline marking on the synch pair
2025-07-02 06:41:18.531 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.531 if eqi is None:
2025-07-02 06:41:18.531 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.531 atags = btags = ""
2025-07-02 06:41:18.531 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.531 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.531 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.531 if tag == 'replace':
2025-07-02 06:41:18.531 atags += '^' * la
2025-07-02 06:41:18.531 btags += '^' * lb
2025-07-02 06:41:18.531 elif tag == 'delete':
2025-07-02 06:41:18.531 atags += '-' * la
2025-07-02 06:41:18.531 elif tag == 'insert':
2025-07-02 06:41:18.531 btags += '+' * lb
2025-07-02 06:41:18.532 elif tag == 'equal':
2025-07-02 06:41:18.532 atags += ' ' * la
2025-07-02 06:41:18.532 btags += ' ' * lb
2025-07-02 06:41:18.532 else:
2025-07-02 06:41:18.532 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.532 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.532 else:
2025-07-02 06:41:18.532 # the synch pair is identical
2025-07-02 06:41:18.532 yield ' ' + aelt
2025-07-02 06:41:18.532
2025-07-02 06:41:18.532 # pump out diffs from after the synch point
2025-07-02 06:41:18.532 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.532
2025-07-02 06:41:18.532 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.532 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.532
2025-07-02 06:41:18.532 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.532 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.532 alo = 415, ahi = 1101
2025-07-02 06:41:18.533 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.533 blo = 415, bhi = 1101
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.533 g = []
2025-07-02 06:41:18.533 if alo < ahi:
2025-07-02 06:41:18.533 if blo < bhi:
2025-07-02 06:41:18.533 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.533 else:
2025-07-02 06:41:18.533 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.533 elif blo < bhi:
2025-07-02 06:41:18.533 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 > yield from g
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.533 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.533 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.534 alo = 415, ahi = 1101
2025-07-02 06:41:18.534 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.534 blo = 415, bhi = 1101
2025-07-02 06:41:18.534
2025-07-02 06:41:18.534 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.534 r"""
2025-07-02 06:41:18.534 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.534 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.534 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.534 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.534
2025-07-02 06:41:18.534 Example:
2025-07-02 06:41:18.534
2025-07-02 06:41:18.534 >>> d = Differ()
2025-07-02 06:41:18.534 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.534 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.534 >>> print(''.join(results), end="")
2025-07-02 06:41:18.535 - abcDefghiJkl
2025-07-02 06:41:18.535 + abcdefGhijkl
2025-07-02 06:41:18.535 """
2025-07-02 06:41:18.535
2025-07-02 06:41:18.535 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.535 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.535 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.535 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.535 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.535
2025-07-02 06:41:18.535 # search for the pair that matches best without being identical
2025-07-02 06:41:18.535 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.535 # on junk -- unless we have to)
2025-07-02 06:41:18.535 for j in range(blo, bhi):
2025-07-02 06:41:18.535 bj = b[j]
2025-07-02 06:41:18.535 cruncher.set_seq2(bj)
2025-07-02 06:41:18.535 for i in range(alo, ahi):
2025-07-02 06:41:18.536 ai = a[i]
2025-07-02 06:41:18.536 if ai == bj:
2025-07-02 06:41:18.536 if eqi is None:
2025-07-02 06:41:18.536 eqi, eqj = i, j
2025-07-02 06:41:18.536 continue
2025-07-02 06:41:18.536 cruncher.set_seq1(ai)
2025-07-02 06:41:18.536 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.536 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.536 # compares by a factor of 3.
2025-07-02 06:41:18.536 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.536 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.536 # of the computation is cached by cruncher
2025-07-02 06:41:18.536 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.536 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.536 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.536 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.536 if best_ratio < cutoff:
2025-07-02 06:41:18.536 # no non-identical "pretty close" pair
2025-07-02 06:41:18.537 if eqi is None:
2025-07-02 06:41:18.537 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.537 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.537 return
2025-07-02 06:41:18.537 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.537 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.537 else:
2025-07-02 06:41:18.537 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.537 eqi = None
2025-07-02 06:41:18.537
2025-07-02 06:41:18.537 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.537 # identical
2025-07-02 06:41:18.537
2025-07-02 06:41:18.537 # pump out diffs from before the synch point
2025-07-02 06:41:18.537 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.537
2025-07-02 06:41:18.537 # do intraline marking on the synch pair
2025-07-02 06:41:18.537 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.537 if eqi is None:
2025-07-02 06:41:18.538 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.538 atags = btags = ""
2025-07-02 06:41:18.538 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.538 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.538 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.538 if tag == 'replace':
2025-07-02 06:41:18.538 atags += '^' * la
2025-07-02 06:41:18.538 btags += '^' * lb
2025-07-02 06:41:18.538 elif tag == 'delete':
2025-07-02 06:41:18.538 atags += '-' * la
2025-07-02 06:41:18.538 elif tag == 'insert':
2025-07-02 06:41:18.538 btags += '+' * lb
2025-07-02 06:41:18.538 elif tag == 'equal':
2025-07-02 06:41:18.538 atags += ' ' * la
2025-07-02 06:41:18.538 btags += ' ' * lb
2025-07-02 06:41:18.538 else:
2025-07-02 06:41:18.538 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.538 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.538 else:
2025-07-02 06:41:18.538 # the synch pair is identical
2025-07-02 06:41:18.539 yield ' ' + aelt
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539 # pump out diffs from after the synch point
2025-07-02 06:41:18.539 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.539 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.539 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.539 alo = 416, ahi = 1101
2025-07-02 06:41:18.539 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.539 blo = 416, bhi = 1101
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.539 g = []
2025-07-02 06:41:18.539 if alo < ahi:
2025-07-02 06:41:18.539 if blo < bhi:
2025-07-02 06:41:18.540 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.540 else:
2025-07-02 06:41:18.540 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.540 elif blo < bhi:
2025-07-02 06:41:18.540 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 > yield from g
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.540 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.540 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.540 alo = 416, ahi = 1101
2025-07-02 06:41:18.540 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.540 blo = 416, bhi = 1101
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.540 r"""
2025-07-02 06:41:18.541 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.541 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.541 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.541 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.541
2025-07-02 06:41:18.541 Example:
2025-07-02 06:41:18.541
2025-07-02 06:41:18.541 >>> d = Differ()
2025-07-02 06:41:18.541 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.541 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.541 >>> print(''.join(results), end="")
2025-07-02 06:41:18.541 - abcDefghiJkl
2025-07-02 06:41:18.541 + abcdefGhijkl
2025-07-02 06:41:18.541 """
2025-07-02 06:41:18.541
2025-07-02 06:41:18.541 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.541 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.542 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.542 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.542 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.542
2025-07-02 06:41:18.542 # search for the pair that matches best without being identical
2025-07-02 06:41:18.542 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.542 # on junk -- unless we have to)
2025-07-02 06:41:18.542 for j in range(blo, bhi):
2025-07-02 06:41:18.542 bj = b[j]
2025-07-02 06:41:18.542 cruncher.set_seq2(bj)
2025-07-02 06:41:18.542 for i in range(alo, ahi):
2025-07-02 06:41:18.542 ai = a[i]
2025-07-02 06:41:18.542 if ai == bj:
2025-07-02 06:41:18.542 if eqi is None:
2025-07-02 06:41:18.542 eqi, eqj = i, j
2025-07-02 06:41:18.542 continue
2025-07-02 06:41:18.542 cruncher.set_seq1(ai)
2025-07-02 06:41:18.542 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.542 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.543 # compares by a factor of 3.
2025-07-02 06:41:18.543 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.543 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.543 # of the computation is cached by cruncher
2025-07-02 06:41:18.543 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.543 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.543 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.543 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.543 if best_ratio < cutoff:
2025-07-02 06:41:18.543 # no non-identical "pretty close" pair
2025-07-02 06:41:18.543 if eqi is None:
2025-07-02 06:41:18.543 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.543 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.543 return
2025-07-02 06:41:18.543 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.543 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.543 else:
2025-07-02 06:41:18.543 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.544 eqi = None
2025-07-02 06:41:18.544
2025-07-02 06:41:18.544 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.544 # identical
2025-07-02 06:41:18.544
2025-07-02 06:41:18.544 # pump out diffs from before the synch point
2025-07-02 06:41:18.544 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.544
2025-07-02 06:41:18.544 # do intraline marking on the synch pair
2025-07-02 06:41:18.544 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.544 if eqi is None:
2025-07-02 06:41:18.544 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.544 atags = btags = ""
2025-07-02 06:41:18.544 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.544 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.544 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.544 if tag == 'replace':
2025-07-02 06:41:18.544 atags += '^' * la
2025-07-02 06:41:18.544 btags += '^' * lb
2025-07-02 06:41:18.545 elif tag == 'delete':
2025-07-02 06:41:18.545 atags += '-' * la
2025-07-02 06:41:18.545 elif tag == 'insert':
2025-07-02 06:41:18.545 btags += '+' * lb
2025-07-02 06:41:18.545 elif tag == 'equal':
2025-07-02 06:41:18.545 atags += ' ' * la
2025-07-02 06:41:18.545 btags += ' ' * lb
2025-07-02 06:41:18.545 else:
2025-07-02 06:41:18.545 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.545 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.545 else:
2025-07-02 06:41:18.545 # the synch pair is identical
2025-07-02 06:41:18.545 yield ' ' + aelt
2025-07-02 06:41:18.545
2025-07-02 06:41:18.545 # pump out diffs from after the synch point
2025-07-02 06:41:18.545 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.545
2025-07-02 06:41:18.545 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.545 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.546
2025-07-02 06:41:18.546 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.546 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.546 alo = 417, ahi = 1101
2025-07-02 06:41:18.546 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.546 blo = 417, bhi = 1101
2025-07-02 06:41:18.546
2025-07-02 06:41:18.546 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.546 g = []
2025-07-02 06:41:18.546 if alo < ahi:
2025-07-02 06:41:18.546 if blo < bhi:
2025-07-02 06:41:18.546 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.546 else:
2025-07-02 06:41:18.546 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.546 elif blo < bhi:
2025-07-02 06:41:18.546 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.546
2025-07-02 06:41:18.546 > yield from g
2025-07-02 06:41:18.546
2025-07-02 06:41:18.547 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.547 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.547
2025-07-02 06:41:18.547 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.547 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.547 alo = 417, ahi = 1101
2025-07-02 06:41:18.547 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.547 blo = 417, bhi = 1101
2025-07-02 06:41:18.547
2025-07-02 06:41:18.547 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.547 r"""
2025-07-02 06:41:18.547 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.547 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.547 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.547 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.547
2025-07-02 06:41:18.547 Example:
2025-07-02 06:41:18.547
2025-07-02 06:41:18.548 >>> d = Differ()
2025-07-02 06:41:18.548 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.548 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.548 >>> print(''.join(results), end="")
2025-07-02 06:41:18.548 - abcDefghiJkl
2025-07-02 06:41:18.548 + abcdefGhijkl
2025-07-02 06:41:18.548 """
2025-07-02 06:41:18.548
2025-07-02 06:41:18.548 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.548 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.548 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.548 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.548 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.548
2025-07-02 06:41:18.548 # search for the pair that matches best without being identical
2025-07-02 06:41:18.548 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.548 # on junk -- unless we have to)
2025-07-02 06:41:18.549 for j in range(blo, bhi):
2025-07-02 06:41:18.549 bj = b[j]
2025-07-02 06:41:18.549 cruncher.set_seq2(bj)
2025-07-02 06:41:18.549 for i in range(alo, ahi):
2025-07-02 06:41:18.549 ai = a[i]
2025-07-02 06:41:18.549 if ai == bj:
2025-07-02 06:41:18.549 if eqi is None:
2025-07-02 06:41:18.549 eqi, eqj = i, j
2025-07-02 06:41:18.549 continue
2025-07-02 06:41:18.549 cruncher.set_seq1(ai)
2025-07-02 06:41:18.549 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.549 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.549 # compares by a factor of 3.
2025-07-02 06:41:18.549 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.549 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.549 # of the computation is cached by cruncher
2025-07-02 06:41:18.549 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.549 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.549 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.549 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.550 if best_ratio < cutoff:
2025-07-02 06:41:18.550 # no non-identical "pretty close" pair
2025-07-02 06:41:18.550 if eqi is None:
2025-07-02 06:41:18.550 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.550 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.550 return
2025-07-02 06:41:18.550 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.550 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.550 else:
2025-07-02 06:41:18.550 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.550 eqi = None
2025-07-02 06:41:18.550
2025-07-02 06:41:18.550 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.550 # identical
2025-07-02 06:41:18.550
2025-07-02 06:41:18.550 # pump out diffs from before the synch point
2025-07-02 06:41:18.550 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.550
2025-07-02 06:41:18.550 # do intraline marking on the synch pair
2025-07-02 06:41:18.551 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.551 if eqi is None:
2025-07-02 06:41:18.551 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.551 atags = btags = ""
2025-07-02 06:41:18.551 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.551 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.551 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.551 if tag == 'replace':
2025-07-02 06:41:18.551 atags += '^' * la
2025-07-02 06:41:18.551 btags += '^' * lb
2025-07-02 06:41:18.551 elif tag == 'delete':
2025-07-02 06:41:18.551 atags += '-' * la
2025-07-02 06:41:18.551 elif tag == 'insert':
2025-07-02 06:41:18.551 btags += '+' * lb
2025-07-02 06:41:18.551 elif tag == 'equal':
2025-07-02 06:41:18.551 atags += ' ' * la
2025-07-02 06:41:18.551 btags += ' ' * lb
2025-07-02 06:41:18.551 else:
2025-07-02 06:41:18.551 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.551 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.552 else:
2025-07-02 06:41:18.552 # the synch pair is identical
2025-07-02 06:41:18.552 yield ' ' + aelt
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552 # pump out diffs from after the synch point
2025-07-02 06:41:18.552 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.552 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.552 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.552 alo = 418, ahi = 1101
2025-07-02 06:41:18.552 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.552 blo = 418, bhi = 1101
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.553 g = []
2025-07-02 06:41:18.553 if alo < ahi:
2025-07-02 06:41:18.553 if blo < bhi:
2025-07-02 06:41:18.553 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.553 else:
2025-07-02 06:41:18.553 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.553 elif blo < bhi:
2025-07-02 06:41:18.553 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.553
2025-07-02 06:41:18.553 > yield from g
2025-07-02 06:41:18.553
2025-07-02 06:41:18.553 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.553 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.553
2025-07-02 06:41:18.553 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.553 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.553 alo = 418, ahi = 1101
2025-07-02 06:41:18.553 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.553 blo = 418, bhi = 1101
2025-07-02 06:41:18.554
2025-07-02 06:41:18.554 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.554 r"""
2025-07-02 06:41:18.554 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.554 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.554 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.554 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.554
2025-07-02 06:41:18.554 Example:
2025-07-02 06:41:18.554
2025-07-02 06:41:18.554 >>> d = Differ()
2025-07-02 06:41:18.554 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.554 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.554 >>> print(''.join(results), end="")
2025-07-02 06:41:18.554 - abcDefghiJkl
2025-07-02 06:41:18.554 + abcdefGhijkl
2025-07-02 06:41:18.554 """
2025-07-02 06:41:18.555
2025-07-02 06:41:18.555 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.555 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.555 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.555 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.555 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.555
2025-07-02 06:41:18.555 # search for the pair that matches best without being identical
2025-07-02 06:41:18.555 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.555 # on junk -- unless we have to)
2025-07-02 06:41:18.555 for j in range(blo, bhi):
2025-07-02 06:41:18.555 bj = b[j]
2025-07-02 06:41:18.555 cruncher.set_seq2(bj)
2025-07-02 06:41:18.555 for i in range(alo, ahi):
2025-07-02 06:41:18.555 ai = a[i]
2025-07-02 06:41:18.555 if ai == bj:
2025-07-02 06:41:18.555 if eqi is None:
2025-07-02 06:41:18.555 eqi, eqj = i, j
2025-07-02 06:41:18.555 continue
2025-07-02 06:41:18.556 cruncher.set_seq1(ai)
2025-07-02 06:41:18.556 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.556 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.556 # compares by a factor of 3.
2025-07-02 06:41:18.556 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.556 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.556 # of the computation is cached by cruncher
2025-07-02 06:41:18.556 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.556 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.556 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.556 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.556 if best_ratio < cutoff:
2025-07-02 06:41:18.556 # no non-identical "pretty close" pair
2025-07-02 06:41:18.556 if eqi is None:
2025-07-02 06:41:18.556 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.556 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.556 return
2025-07-02 06:41:18.556 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.556 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.557 else:
2025-07-02 06:41:18.557 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.557 eqi = None
2025-07-02 06:41:18.557
2025-07-02 06:41:18.557 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.557 # identical
2025-07-02 06:41:18.557
2025-07-02 06:41:18.557 # pump out diffs from before the synch point
2025-07-02 06:41:18.557 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.557
2025-07-02 06:41:18.557 # do intraline marking on the synch pair
2025-07-02 06:41:18.557 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.557 if eqi is None:
2025-07-02 06:41:18.557 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.557 atags = btags = ""
2025-07-02 06:41:18.557 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.557 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.557 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.557 if tag == 'replace':
2025-07-02 06:41:18.558 atags += '^' * la
2025-07-02 06:41:18.558 btags += '^' * lb
2025-07-02 06:41:18.558 elif tag == 'delete':
2025-07-02 06:41:18.558 atags += '-' * la
2025-07-02 06:41:18.558 elif tag == 'insert':
2025-07-02 06:41:18.558 btags += '+' * lb
2025-07-02 06:41:18.558 elif tag == 'equal':
2025-07-02 06:41:18.558 atags += ' ' * la
2025-07-02 06:41:18.558 btags += ' ' * lb
2025-07-02 06:41:18.558 else:
2025-07-02 06:41:18.558 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.558 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.558 else:
2025-07-02 06:41:18.558 # the synch pair is identical
2025-07-02 06:41:18.558 yield ' ' + aelt
2025-07-02 06:41:18.558
2025-07-02 06:41:18.558 # pump out diffs from after the synch point
2025-07-02 06:41:18.558 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.558
2025-07-02 06:41:18.559 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.559 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.559
2025-07-02 06:41:18.559 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.559 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.559 alo = 419, ahi = 1101
2025-07-02 06:41:18.559 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.559 blo = 419, bhi = 1101
2025-07-02 06:41:18.559
2025-07-02 06:41:18.559 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.559 g = []
2025-07-02 06:41:18.559 if alo < ahi:
2025-07-02 06:41:18.559 if blo < bhi:
2025-07-02 06:41:18.559 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.559 else:
2025-07-02 06:41:18.559 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.559 elif blo < bhi:
2025-07-02 06:41:18.559 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.559
2025-07-02 06:41:18.560 > yield from g
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.560 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.560 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.560 alo = 419, ahi = 1101
2025-07-02 06:41:18.560 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.560 blo = 419, bhi = 1101
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.560 r"""
2025-07-02 06:41:18.560 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.560 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.560 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.560 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560 Example:
2025-07-02 06:41:18.561
2025-07-02 06:41:18.561 >>> d = Differ()
2025-07-02 06:41:18.561 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.561 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.561 >>> print(''.join(results), end="")
2025-07-02 06:41:18.561 - abcDefghiJkl
2025-07-02 06:41:18.561 + abcdefGhijkl
2025-07-02 06:41:18.561 """
2025-07-02 06:41:18.561
2025-07-02 06:41:18.561 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.561 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.561 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.561 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.561 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.561
2025-07-02 06:41:18.561 # search for the pair that matches best without being identical
2025-07-02 06:41:18.562 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.562 # on junk -- unless we have to)
2025-07-02 06:41:18.562 for j in range(blo, bhi):
2025-07-02 06:41:18.562 bj = b[j]
2025-07-02 06:41:18.562 cruncher.set_seq2(bj)
2025-07-02 06:41:18.562 for i in range(alo, ahi):
2025-07-02 06:41:18.562 ai = a[i]
2025-07-02 06:41:18.562 if ai == bj:
2025-07-02 06:41:18.562 if eqi is None:
2025-07-02 06:41:18.562 eqi, eqj = i, j
2025-07-02 06:41:18.562 continue
2025-07-02 06:41:18.562 cruncher.set_seq1(ai)
2025-07-02 06:41:18.562 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.562 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.562 # compares by a factor of 3.
2025-07-02 06:41:18.562 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.562 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.562 # of the computation is cached by cruncher
2025-07-02 06:41:18.562 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.563 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.563 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.563 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.563 if best_ratio < cutoff:
2025-07-02 06:41:18.563 # no non-identical "pretty close" pair
2025-07-02 06:41:18.563 if eqi is None:
2025-07-02 06:41:18.563 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.564 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.564 return
2025-07-02 06:41:18.564 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.564 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.564 else:
2025-07-02 06:41:18.564 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.564 eqi = None
2025-07-02 06:41:18.564
2025-07-02 06:41:18.564 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.564 # identical
2025-07-02 06:41:18.564
2025-07-02 06:41:18.564 # pump out diffs from before the synch point
2025-07-02 06:41:18.564 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.564
2025-07-02 06:41:18.564 # do intraline marking on the synch pair
2025-07-02 06:41:18.564 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.564 if eqi is None:
2025-07-02 06:41:18.565 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.565 atags = btags = ""
2025-07-02 06:41:18.565 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.565 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.565 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.565 if tag == 'replace':
2025-07-02 06:41:18.565 atags += '^' * la
2025-07-02 06:41:18.565 btags += '^' * lb
2025-07-02 06:41:18.565 elif tag == 'delete':
2025-07-02 06:41:18.565 atags += '-' * la
2025-07-02 06:41:18.565 elif tag == 'insert':
2025-07-02 06:41:18.565 btags += '+' * lb
2025-07-02 06:41:18.565 elif tag == 'equal':
2025-07-02 06:41:18.565 atags += ' ' * la
2025-07-02 06:41:18.565 btags += ' ' * lb
2025-07-02 06:41:18.565 else:
2025-07-02 06:41:18.565 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.566 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.566 else:
2025-07-02 06:41:18.566 # the synch pair is identical
2025-07-02 06:41:18.566 yield ' ' + aelt
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566 # pump out diffs from after the synch point
2025-07-02 06:41:18.566 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.566 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.566 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.566 alo = 422, ahi = 1101
2025-07-02 06:41:18.566 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.566 blo = 422, bhi = 1101
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.566 g = []
2025-07-02 06:41:18.566 if alo < ahi:
2025-07-02 06:41:18.566 if blo < bhi:
2025-07-02 06:41:18.566 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.566 else:
2025-07-02 06:41:18.566 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.566 elif blo < bhi:
2025-07-02 06:41:18.567 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 > yield from g
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.567 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.567 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.567 alo = 422, ahi = 1101
2025-07-02 06:41:18.567 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.567 blo = 422, bhi = 1101
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.567 r"""
2025-07-02 06:41:18.567 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.567 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.567 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.567 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568 Example:
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568 >>> d = Differ()
2025-07-02 06:41:18.568 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.568 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.568 >>> print(''.join(results), end="")
2025-07-02 06:41:18.568 - abcDefghiJkl
2025-07-02 06:41:18.568 + abcdefGhijkl
2025-07-02 06:41:18.568 """
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.568 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.568 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.568 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.568 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568 # search for the pair that matches best without being identical
2025-07-02 06:41:18.569 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.569 # on junk -- unless we have to)
2025-07-02 06:41:18.569 for j in range(blo, bhi):
2025-07-02 06:41:18.569 bj = b[j]
2025-07-02 06:41:18.569 cruncher.set_seq2(bj)
2025-07-02 06:41:18.569 for i in range(alo, ahi):
2025-07-02 06:41:18.569 ai = a[i]
2025-07-02 06:41:18.569 if ai == bj:
2025-07-02 06:41:18.569 if eqi is None:
2025-07-02 06:41:18.569 eqi, eqj = i, j
2025-07-02 06:41:18.569 continue
2025-07-02 06:41:18.569 cruncher.set_seq1(ai)
2025-07-02 06:41:18.569 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.569 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.569 # compares by a factor of 3.
2025-07-02 06:41:18.569 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.569 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.569 # of the computation is cached by cruncher
2025-07-02 06:41:18.569 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.570 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.570 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.570 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.570 if best_ratio < cutoff:
2025-07-02 06:41:18.570 # no non-identical "pretty close" pair
2025-07-02 06:41:18.570 if eqi is None:
2025-07-02 06:41:18.570 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.570 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.570 return
2025-07-02 06:41:18.570 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.570 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.570 else:
2025-07-02 06:41:18.570 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.570 eqi = None
2025-07-02 06:41:18.570
2025-07-02 06:41:18.570 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.570 # identical
2025-07-02 06:41:18.570
2025-07-02 06:41:18.570 # pump out diffs from before the synch point
2025-07-02 06:41:18.570 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.571
2025-07-02 06:41:18.571 # do intraline marking on the synch pair
2025-07-02 06:41:18.571 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.571 if eqi is None:
2025-07-02 06:41:18.571 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.571 atags = btags = ""
2025-07-02 06:41:18.571 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.571 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.571 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.571 if tag == 'replace':
2025-07-02 06:41:18.571 atags += '^' * la
2025-07-02 06:41:18.571 btags += '^' * lb
2025-07-02 06:41:18.571 elif tag == 'delete':
2025-07-02 06:41:18.571 atags += '-' * la
2025-07-02 06:41:18.571 elif tag == 'insert':
2025-07-02 06:41:18.571 btags += '+' * lb
2025-07-02 06:41:18.571 elif tag == 'equal':
2025-07-02 06:41:18.571 atags += ' ' * la
2025-07-02 06:41:18.572 btags += ' ' * lb
2025-07-02 06:41:18.572 else:
2025-07-02 06:41:18.572 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.572 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.572 else:
2025-07-02 06:41:18.572 # the synch pair is identical
2025-07-02 06:41:18.572 yield ' ' + aelt
2025-07-02 06:41:18.572
2025-07-02 06:41:18.572 # pump out diffs from after the synch point
2025-07-02 06:41:18.572 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.572
2025-07-02 06:41:18.572 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.572 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.572
2025-07-02 06:41:18.572 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.572 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.572 alo = 423, ahi = 1101
2025-07-02 06:41:18.572 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.572 blo = 423, bhi = 1101
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.573 g = []
2025-07-02 06:41:18.573 if alo < ahi:
2025-07-02 06:41:18.573 if blo < bhi:
2025-07-02 06:41:18.573 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.573 else:
2025-07-02 06:41:18.573 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.573 elif blo < bhi:
2025-07-02 06:41:18.573 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 > yield from g
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.573 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.573 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.573 alo = 423, ahi = 1101
2025-07-02 06:41:18.574 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.574 blo = 423, bhi = 1101
2025-07-02 06:41:18.574
2025-07-02 06:41:18.574 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.574 r"""
2025-07-02 06:41:18.574 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.574 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.574 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.574 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.574
2025-07-02 06:41:18.574 Example:
2025-07-02 06:41:18.574
2025-07-02 06:41:18.574 >>> d = Differ()
2025-07-02 06:41:18.574 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.574 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.574 >>> print(''.join(results), end="")
2025-07-02 06:41:18.574 - abcDefghiJkl
2025-07-02 06:41:18.574 + abcdefGhijkl
2025-07-02 06:41:18.575 """
2025-07-02 06:41:18.575
2025-07-02 06:41:18.575 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.575 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.575 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.575 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.575 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.575
2025-07-02 06:41:18.575 # search for the pair that matches best without being identical
2025-07-02 06:41:18.575 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.575 # on junk -- unless we have to)
2025-07-02 06:41:18.575 for j in range(blo, bhi):
2025-07-02 06:41:18.575 bj = b[j]
2025-07-02 06:41:18.575 cruncher.set_seq2(bj)
2025-07-02 06:41:18.575 for i in range(alo, ahi):
2025-07-02 06:41:18.575 ai = a[i]
2025-07-02 06:41:18.575 if ai == bj:
2025-07-02 06:41:18.575 if eqi is None:
2025-07-02 06:41:18.575 eqi, eqj = i, j
2025-07-02 06:41:18.576 continue
2025-07-02 06:41:18.576 cruncher.set_seq1(ai)
2025-07-02 06:41:18.576 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.576 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.576 # compares by a factor of 3.
2025-07-02 06:41:18.576 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.576 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.576 # of the computation is cached by cruncher
2025-07-02 06:41:18.576 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.576 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.576 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.576 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.576 if best_ratio < cutoff:
2025-07-02 06:41:18.576 # no non-identical "pretty close" pair
2025-07-02 06:41:18.576 if eqi is None:
2025-07-02 06:41:18.576 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.576 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.576 return
2025-07-02 06:41:18.576 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.576 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.577 else:
2025-07-02 06:41:18.577 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.577 eqi = None
2025-07-02 06:41:18.577
2025-07-02 06:41:18.577 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.577 # identical
2025-07-02 06:41:18.577
2025-07-02 06:41:18.577 # pump out diffs from before the synch point
2025-07-02 06:41:18.577 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.577
2025-07-02 06:41:18.577 # do intraline marking on the synch pair
2025-07-02 06:41:18.577 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.577 if eqi is None:
2025-07-02 06:41:18.577 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.577 atags = btags = ""
2025-07-02 06:41:18.577 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.577 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.577 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.577 if tag == 'replace':
2025-07-02 06:41:18.578 atags += '^' * la
2025-07-02 06:41:18.578 btags += '^' * lb
2025-07-02 06:41:18.578 elif tag == 'delete':
2025-07-02 06:41:18.578 atags += '-' * la
2025-07-02 06:41:18.578 elif tag == 'insert':
2025-07-02 06:41:18.578 btags += '+' * lb
2025-07-02 06:41:18.578 elif tag == 'equal':
2025-07-02 06:41:18.578 atags += ' ' * la
2025-07-02 06:41:18.578 btags += ' ' * lb
2025-07-02 06:41:18.578 else:
2025-07-02 06:41:18.578 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.578 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.578 else:
2025-07-02 06:41:18.578 # the synch pair is identical
2025-07-02 06:41:18.578 yield ' ' + aelt
2025-07-02 06:41:18.578
2025-07-02 06:41:18.578 # pump out diffs from after the synch point
2025-07-02 06:41:18.578 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.578
2025-07-02 06:41:18.578 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.579 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.579
2025-07-02 06:41:18.579 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.579 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.579 alo = 424, ahi = 1101
2025-07-02 06:41:18.579 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.579 blo = 424, bhi = 1101
2025-07-02 06:41:18.579
2025-07-02 06:41:18.579 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.579 g = []
2025-07-02 06:41:18.579 if alo < ahi:
2025-07-02 06:41:18.579 if blo < bhi:
2025-07-02 06:41:18.579 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.579 else:
2025-07-02 06:41:18.579 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.579 elif blo < bhi:
2025-07-02 06:41:18.579 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.579
2025-07-02 06:41:18.579 > yield from g
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.580 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.580 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.580 alo = 424, ahi = 1101
2025-07-02 06:41:18.580 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.580 blo = 424, bhi = 1101
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.580 r"""
2025-07-02 06:41:18.580 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.580 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.580 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.580 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580 Example:
2025-07-02 06:41:18.581
2025-07-02 06:41:18.581 >>> d = Differ()
2025-07-02 06:41:18.581 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.581 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.581 >>> print(''.join(results), end="")
2025-07-02 06:41:18.581 - abcDefghiJkl
2025-07-02 06:41:18.581 + abcdefGhijkl
2025-07-02 06:41:18.581 """
2025-07-02 06:41:18.581
2025-07-02 06:41:18.581 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.581 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.581 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.581 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.581 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.581
2025-07-02 06:41:18.581 # search for the pair that matches best without being identical
2025-07-02 06:41:18.581 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.581 # on junk -- unless we have to)
2025-07-02 06:41:18.582 for j in range(blo, bhi):
2025-07-02 06:41:18.582 bj = b[j]
2025-07-02 06:41:18.582 cruncher.set_seq2(bj)
2025-07-02 06:41:18.582 for i in range(alo, ahi):
2025-07-02 06:41:18.582 ai = a[i]
2025-07-02 06:41:18.582 if ai == bj:
2025-07-02 06:41:18.582 if eqi is None:
2025-07-02 06:41:18.582 eqi, eqj = i, j
2025-07-02 06:41:18.582 continue
2025-07-02 06:41:18.582 cruncher.set_seq1(ai)
2025-07-02 06:41:18.582 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.582 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.582 # compares by a factor of 3.
2025-07-02 06:41:18.582 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.582 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.582 # of the computation is cached by cruncher
2025-07-02 06:41:18.582 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.582 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.582 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.583 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.583 if best_ratio < cutoff:
2025-07-02 06:41:18.583 # no non-identical "pretty close" pair
2025-07-02 06:41:18.583 if eqi is None:
2025-07-02 06:41:18.583 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.583 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.583 return
2025-07-02 06:41:18.583 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.583 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.583 else:
2025-07-02 06:41:18.583 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.583 eqi = None
2025-07-02 06:41:18.583
2025-07-02 06:41:18.583 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.583 # identical
2025-07-02 06:41:18.583
2025-07-02 06:41:18.583 # pump out diffs from before the synch point
2025-07-02 06:41:18.583 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.583
2025-07-02 06:41:18.584 # do intraline marking on the synch pair
2025-07-02 06:41:18.584 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.584 if eqi is None:
2025-07-02 06:41:18.584 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.584 atags = btags = ""
2025-07-02 06:41:18.584 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.584 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.584 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.584 if tag == 'replace':
2025-07-02 06:41:18.584 atags += '^' * la
2025-07-02 06:41:18.584 btags += '^' * lb
2025-07-02 06:41:18.584 elif tag == 'delete':
2025-07-02 06:41:18.584 atags += '-' * la
2025-07-02 06:41:18.584 elif tag == 'insert':
2025-07-02 06:41:18.584 btags += '+' * lb
2025-07-02 06:41:18.584 elif tag == 'equal':
2025-07-02 06:41:18.584 atags += ' ' * la
2025-07-02 06:41:18.584 btags += ' ' * lb
2025-07-02 06:41:18.584 else:
2025-07-02 06:41:18.584 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.585 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.585 else:
2025-07-02 06:41:18.585 # the synch pair is identical
2025-07-02 06:41:18.585 yield ' ' + aelt
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585 # pump out diffs from after the synch point
2025-07-02 06:41:18.585 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.585 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.585 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.585 alo = 425, ahi = 1101
2025-07-02 06:41:18.585 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.585 blo = 425, bhi = 1101
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.585 g = []
2025-07-02 06:41:18.586 if alo < ahi:
2025-07-02 06:41:18.586 if blo < bhi:
2025-07-02 06:41:18.586 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.586 else:
2025-07-02 06:41:18.586 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.586 elif blo < bhi:
2025-07-02 06:41:18.586 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.586
2025-07-02 06:41:18.586 > yield from g
2025-07-02 06:41:18.586
2025-07-02 06:41:18.586 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.586 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.586
2025-07-02 06:41:18.586 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.586 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.586 alo = 425, ahi = 1101
2025-07-02 06:41:18.586 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.586 blo = 425, bhi = 1101
2025-07-02 06:41:18.586
2025-07-02 06:41:18.587 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.587 r"""
2025-07-02 06:41:18.587 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.587 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.587 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.587 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.587
2025-07-02 06:41:18.587 Example:
2025-07-02 06:41:18.587
2025-07-02 06:41:18.587 >>> d = Differ()
2025-07-02 06:41:18.587 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.587 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.587 >>> print(''.join(results), end="")
2025-07-02 06:41:18.587 - abcDefghiJkl
2025-07-02 06:41:18.587 + abcdefGhijkl
2025-07-02 06:41:18.587 """
2025-07-02 06:41:18.587
2025-07-02 06:41:18.587 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.588 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.588 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.588 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.588 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.588
2025-07-02 06:41:18.588 # search for the pair that matches best without being identical
2025-07-02 06:41:18.588 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.588 # on junk -- unless we have to)
2025-07-02 06:41:18.588 for j in range(blo, bhi):
2025-07-02 06:41:18.588 bj = b[j]
2025-07-02 06:41:18.588 cruncher.set_seq2(bj)
2025-07-02 06:41:18.588 for i in range(alo, ahi):
2025-07-02 06:41:18.588 ai = a[i]
2025-07-02 06:41:18.588 if ai == bj:
2025-07-02 06:41:18.588 if eqi is None:
2025-07-02 06:41:18.588 eqi, eqj = i, j
2025-07-02 06:41:18.588 continue
2025-07-02 06:41:18.588 cruncher.set_seq1(ai)
2025-07-02 06:41:18.588 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.588 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.589 # compares by a factor of 3.
2025-07-02 06:41:18.589 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.589 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.589 # of the computation is cached by cruncher
2025-07-02 06:41:18.589 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.589 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.589 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.589 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.589 if best_ratio < cutoff:
2025-07-02 06:41:18.589 # no non-identical "pretty close" pair
2025-07-02 06:41:18.589 if eqi is None:
2025-07-02 06:41:18.589 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.589 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.589 return
2025-07-02 06:41:18.589 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.589 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.589 else:
2025-07-02 06:41:18.589 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.590 eqi = None
2025-07-02 06:41:18.590
2025-07-02 06:41:18.590 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.590 # identical
2025-07-02 06:41:18.590
2025-07-02 06:41:18.590 # pump out diffs from before the synch point
2025-07-02 06:41:18.590 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.590
2025-07-02 06:41:18.590 # do intraline marking on the synch pair
2025-07-02 06:41:18.590 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.590 if eqi is None:
2025-07-02 06:41:18.590 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.590 atags = btags = ""
2025-07-02 06:41:18.590 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.590 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.590 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.590 if tag == 'replace':
2025-07-02 06:41:18.590 atags += '^' * la
2025-07-02 06:41:18.590 btags += '^' * lb
2025-07-02 06:41:18.591 elif tag == 'delete':
2025-07-02 06:41:18.591 atags += '-' * la
2025-07-02 06:41:18.591 elif tag == 'insert':
2025-07-02 06:41:18.591 btags += '+' * lb
2025-07-02 06:41:18.591 elif tag == 'equal':
2025-07-02 06:41:18.591 atags += ' ' * la
2025-07-02 06:41:18.591 btags += ' ' * lb
2025-07-02 06:41:18.591 else:
2025-07-02 06:41:18.591 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.591 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.591 else:
2025-07-02 06:41:18.591 # the synch pair is identical
2025-07-02 06:41:18.591 yield ' ' + aelt
2025-07-02 06:41:18.591
2025-07-02 06:41:18.591 # pump out diffs from after the synch point
2025-07-02 06:41:18.591 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.591
2025-07-02 06:41:18.591 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.591 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.591
2025-07-02 06:41:18.591 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.592 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.592 alo = 426, ahi = 1101
2025-07-02 06:41:18.592 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.592 blo = 426, bhi = 1101
2025-07-02 06:41:18.592
2025-07-02 06:41:18.592 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.592 g = []
2025-07-02 06:41:18.592 if alo < ahi:
2025-07-02 06:41:18.592 if blo < bhi:
2025-07-02 06:41:18.592 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.592 else:
2025-07-02 06:41:18.592 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.592 elif blo < bhi:
2025-07-02 06:41:18.592 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.592
2025-07-02 06:41:18.592 > yield from g
2025-07-02 06:41:18.592
2025-07-02 06:41:18.592 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.592 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.592
2025-07-02 06:41:18.593 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.593 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.593 alo = 426, ahi = 1101
2025-07-02 06:41:18.593 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.593 blo = 426, bhi = 1101
2025-07-02 06:41:18.593
2025-07-02 06:41:18.593 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.593 r"""
2025-07-02 06:41:18.593 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.593 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.593 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.593 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.593
2025-07-02 06:41:18.593 Example:
2025-07-02 06:41:18.593
2025-07-02 06:41:18.593 >>> d = Differ()
2025-07-02 06:41:18.593 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.593 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.593 >>> print(''.join(results), end="")
2025-07-02 06:41:18.593 - abcDefghiJkl
2025-07-02 06:41:18.594 + abcdefGhijkl
2025-07-02 06:41:18.594 """
2025-07-02 06:41:18.594
2025-07-02 06:41:18.594 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.594 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.594 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.594 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.594 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.594
2025-07-02 06:41:18.594 # search for the pair that matches best without being identical
2025-07-02 06:41:18.594 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.594 # on junk -- unless we have to)
2025-07-02 06:41:18.594 for j in range(blo, bhi):
2025-07-02 06:41:18.594 bj = b[j]
2025-07-02 06:41:18.594 cruncher.set_seq2(bj)
2025-07-02 06:41:18.594 for i in range(alo, ahi):
2025-07-02 06:41:18.594 ai = a[i]
2025-07-02 06:41:18.594 if ai == bj:
2025-07-02 06:41:18.595 if eqi is None:
2025-07-02 06:41:18.595 eqi, eqj = i, j
2025-07-02 06:41:18.595 continue
2025-07-02 06:41:18.595 cruncher.set_seq1(ai)
2025-07-02 06:41:18.595 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.595 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.595 # compares by a factor of 3.
2025-07-02 06:41:18.595 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.595 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.595 # of the computation is cached by cruncher
2025-07-02 06:41:18.595 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.595 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.595 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.595 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.595 if best_ratio < cutoff:
2025-07-02 06:41:18.595 # no non-identical "pretty close" pair
2025-07-02 06:41:18.595 if eqi is None:
2025-07-02 06:41:18.595 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.595 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.596 return
2025-07-02 06:41:18.596 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.596 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.596 else:
2025-07-02 06:41:18.596 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.596 eqi = None
2025-07-02 06:41:18.596
2025-07-02 06:41:18.596 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.596 # identical
2025-07-02 06:41:18.596
2025-07-02 06:41:18.596 # pump out diffs from before the synch point
2025-07-02 06:41:18.596 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.596
2025-07-02 06:41:18.596 # do intraline marking on the synch pair
2025-07-02 06:41:18.596 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.596 if eqi is None:
2025-07-02 06:41:18.596 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.596 atags = btags = ""
2025-07-02 06:41:18.596 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.596 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.597 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.597 if tag == 'replace':
2025-07-02 06:41:18.597 atags += '^' * la
2025-07-02 06:41:18.597 btags += '^' * lb
2025-07-02 06:41:18.597 elif tag == 'delete':
2025-07-02 06:41:18.597 atags += '-' * la
2025-07-02 06:41:18.597 elif tag == 'insert':
2025-07-02 06:41:18.597 btags += '+' * lb
2025-07-02 06:41:18.597 elif tag == 'equal':
2025-07-02 06:41:18.597 atags += ' ' * la
2025-07-02 06:41:18.597 btags += ' ' * lb
2025-07-02 06:41:18.597 else:
2025-07-02 06:41:18.597 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.597 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.597 else:
2025-07-02 06:41:18.597 # the synch pair is identical
2025-07-02 06:41:18.597 yield ' ' + aelt
2025-07-02 06:41:18.597
2025-07-02 06:41:18.597 # pump out diffs from after the synch point
2025-07-02 06:41:18.598 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.598
2025-07-02 06:41:18.598 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.598 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.598
2025-07-02 06:41:18.598 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.598 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.598 alo = 427, ahi = 1101
2025-07-02 06:41:18.598 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.598 blo = 427, bhi = 1101
2025-07-02 06:41:18.598
2025-07-02 06:41:18.598 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.598 g = []
2025-07-02 06:41:18.598 if alo < ahi:
2025-07-02 06:41:18.598 if blo < bhi:
2025-07-02 06:41:18.598 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.598 else:
2025-07-02 06:41:18.598 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.598 elif blo < bhi:
2025-07-02 06:41:18.599 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 > yield from g
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.599 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.599 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.599 alo = 427, ahi = 1101
2025-07-02 06:41:18.599 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.599 blo = 427, bhi = 1101
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.599 r"""
2025-07-02 06:41:18.599 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.599 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.599 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.599 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600 Example:
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600 >>> d = Differ()
2025-07-02 06:41:18.600 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.600 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.600 >>> print(''.join(results), end="")
2025-07-02 06:41:18.600 - abcDefghiJkl
2025-07-02 06:41:18.600 + abcdefGhijkl
2025-07-02 06:41:18.600 """
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.600 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.600 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.600 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.600 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600 # search for the pair that matches best without being identical
2025-07-02 06:41:18.601 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.601 # on junk -- unless we have to)
2025-07-02 06:41:18.601 for j in range(blo, bhi):
2025-07-02 06:41:18.601 bj = b[j]
2025-07-02 06:41:18.601 cruncher.set_seq2(bj)
2025-07-02 06:41:18.601 for i in range(alo, ahi):
2025-07-02 06:41:18.601 ai = a[i]
2025-07-02 06:41:18.601 if ai == bj:
2025-07-02 06:41:18.601 if eqi is None:
2025-07-02 06:41:18.601 eqi, eqj = i, j
2025-07-02 06:41:18.601 continue
2025-07-02 06:41:18.601 cruncher.set_seq1(ai)
2025-07-02 06:41:18.601 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.601 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.601 # compares by a factor of 3.
2025-07-02 06:41:18.601 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.601 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.601 # of the computation is cached by cruncher
2025-07-02 06:41:18.601 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.602 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.602 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.602 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.602 if best_ratio < cutoff:
2025-07-02 06:41:18.602 # no non-identical "pretty close" pair
2025-07-02 06:41:18.602 if eqi is None:
2025-07-02 06:41:18.602 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.602 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.602 return
2025-07-02 06:41:18.602 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.602 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.602 else:
2025-07-02 06:41:18.602 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.602 eqi = None
2025-07-02 06:41:18.602
2025-07-02 06:41:18.602 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.602 # identical
2025-07-02 06:41:18.602
2025-07-02 06:41:18.602 # pump out diffs from before the synch point
2025-07-02 06:41:18.602 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.603
2025-07-02 06:41:18.603 # do intraline marking on the synch pair
2025-07-02 06:41:18.603 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.603 if eqi is None:
2025-07-02 06:41:18.603 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.603 atags = btags = ""
2025-07-02 06:41:18.603 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.603 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.603 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.603 if tag == 'replace':
2025-07-02 06:41:18.603 atags += '^' * la
2025-07-02 06:41:18.603 btags += '^' * lb
2025-07-02 06:41:18.603 elif tag == 'delete':
2025-07-02 06:41:18.603 atags += '-' * la
2025-07-02 06:41:18.603 elif tag == 'insert':
2025-07-02 06:41:18.603 btags += '+' * lb
2025-07-02 06:41:18.603 elif tag == 'equal':
2025-07-02 06:41:18.603 atags += ' ' * la
2025-07-02 06:41:18.603 btags += ' ' * lb
2025-07-02 06:41:18.604 else:
2025-07-02 06:41:18.604 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.604 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.604 else:
2025-07-02 06:41:18.604 # the synch pair is identical
2025-07-02 06:41:18.604 yield ' ' + aelt
2025-07-02 06:41:18.604
2025-07-02 06:41:18.604 # pump out diffs from after the synch point
2025-07-02 06:41:18.604 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.604
2025-07-02 06:41:18.604 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.604 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.604
2025-07-02 06:41:18.604 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.604 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.604 alo = 428, ahi = 1101
2025-07-02 06:41:18.604 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.604 blo = 428, bhi = 1101
2025-07-02 06:41:18.604
2025-07-02 06:41:18.605 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.605 g = []
2025-07-02 06:41:18.605 if alo < ahi:
2025-07-02 06:41:18.605 if blo < bhi:
2025-07-02 06:41:18.605 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.605 else:
2025-07-02 06:41:18.605 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.605 elif blo < bhi:
2025-07-02 06:41:18.605 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.605
2025-07-02 06:41:18.605 > yield from g
2025-07-02 06:41:18.605
2025-07-02 06:41:18.605 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.605 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.605
2025-07-02 06:41:18.605 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.605 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.605 alo = 428, ahi = 1101
2025-07-02 06:41:18.605 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.605 blo = 428, bhi = 1101
2025-07-02 06:41:18.606
2025-07-02 06:41:18.606 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.606 r"""
2025-07-02 06:41:18.606 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.606 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.606 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.606 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.606
2025-07-02 06:41:18.606 Example:
2025-07-02 06:41:18.606
2025-07-02 06:41:18.606 >>> d = Differ()
2025-07-02 06:41:18.606 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.606 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.606 >>> print(''.join(results), end="")
2025-07-02 06:41:18.606 - abcDefghiJkl
2025-07-02 06:41:18.606 + abcdefGhijkl
2025-07-02 06:41:18.606 """
2025-07-02 06:41:18.607
2025-07-02 06:41:18.607 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.607 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.607 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.607 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.607 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.607
2025-07-02 06:41:18.607 # search for the pair that matches best without being identical
2025-07-02 06:41:18.607 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.607 # on junk -- unless we have to)
2025-07-02 06:41:18.607 for j in range(blo, bhi):
2025-07-02 06:41:18.607 bj = b[j]
2025-07-02 06:41:18.607 cruncher.set_seq2(bj)
2025-07-02 06:41:18.607 for i in range(alo, ahi):
2025-07-02 06:41:18.607 ai = a[i]
2025-07-02 06:41:18.607 if ai == bj:
2025-07-02 06:41:18.607 if eqi is None:
2025-07-02 06:41:18.607 eqi, eqj = i, j
2025-07-02 06:41:18.607 continue
2025-07-02 06:41:18.607 cruncher.set_seq1(ai)
2025-07-02 06:41:18.608 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.608 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.608 # compares by a factor of 3.
2025-07-02 06:41:18.608 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.608 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.608 # of the computation is cached by cruncher
2025-07-02 06:41:18.608 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.608 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.608 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.608 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.608 if best_ratio < cutoff:
2025-07-02 06:41:18.608 # no non-identical "pretty close" pair
2025-07-02 06:41:18.608 if eqi is None:
2025-07-02 06:41:18.608 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.608 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.608 return
2025-07-02 06:41:18.608 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.608 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.608 else:
2025-07-02 06:41:18.609 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.609 eqi = None
2025-07-02 06:41:18.609
2025-07-02 06:41:18.609 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.609 # identical
2025-07-02 06:41:18.609
2025-07-02 06:41:18.609 # pump out diffs from before the synch point
2025-07-02 06:41:18.609 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.609
2025-07-02 06:41:18.609 # do intraline marking on the synch pair
2025-07-02 06:41:18.609 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.609 if eqi is None:
2025-07-02 06:41:18.609 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.609 atags = btags = ""
2025-07-02 06:41:18.609 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.609 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.609 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.609 if tag == 'replace':
2025-07-02 06:41:18.609 atags += '^' * la
2025-07-02 06:41:18.610 btags += '^' * lb
2025-07-02 06:41:18.610 elif tag == 'delete':
2025-07-02 06:41:18.610 atags += '-' * la
2025-07-02 06:41:18.610 elif tag == 'insert':
2025-07-02 06:41:18.610 btags += '+' * lb
2025-07-02 06:41:18.610 elif tag == 'equal':
2025-07-02 06:41:18.610 atags += ' ' * la
2025-07-02 06:41:18.610 btags += ' ' * lb
2025-07-02 06:41:18.610 else:
2025-07-02 06:41:18.610 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.610 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.610 else:
2025-07-02 06:41:18.610 # the synch pair is identical
2025-07-02 06:41:18.610 yield ' ' + aelt
2025-07-02 06:41:18.610
2025-07-02 06:41:18.610 # pump out diffs from after the synch point
2025-07-02 06:41:18.610 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.610
2025-07-02 06:41:18.610 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.610 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.611
2025-07-02 06:41:18.611 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.611 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.611 alo = 429, ahi = 1101
2025-07-02 06:41:18.611 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.611 blo = 429, bhi = 1101
2025-07-02 06:41:18.611
2025-07-02 06:41:18.611 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.611 g = []
2025-07-02 06:41:18.611 if alo < ahi:
2025-07-02 06:41:18.611 if blo < bhi:
2025-07-02 06:41:18.611 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.611 else:
2025-07-02 06:41:18.611 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.611 elif blo < bhi:
2025-07-02 06:41:18.611 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.611
2025-07-02 06:41:18.611 > yield from g
2025-07-02 06:41:18.611
2025-07-02 06:41:18.612 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.612 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.612 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.612 alo = 429, ahi = 1101
2025-07-02 06:41:18.612 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.612 blo = 429, bhi = 1101
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.612 r"""
2025-07-02 06:41:18.612 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.612 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.612 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.612 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612 Example:
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612 >>> d = Differ()
2025-07-02 06:41:18.613 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.613 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.613 >>> print(''.join(results), end="")
2025-07-02 06:41:18.613 - abcDefghiJkl
2025-07-02 06:41:18.613 + abcdefGhijkl
2025-07-02 06:41:18.613 """
2025-07-02 06:41:18.613
2025-07-02 06:41:18.613 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.613 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.613 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.613 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.613 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.613
2025-07-02 06:41:18.613 # search for the pair that matches best without being identical
2025-07-02 06:41:18.613 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.613 # on junk -- unless we have to)
2025-07-02 06:41:18.613 for j in range(blo, bhi):
2025-07-02 06:41:18.613 bj = b[j]
2025-07-02 06:41:18.614 cruncher.set_seq2(bj)
2025-07-02 06:41:18.614 for i in range(alo, ahi):
2025-07-02 06:41:18.614 ai = a[i]
2025-07-02 06:41:18.614 if ai == bj:
2025-07-02 06:41:18.614 if eqi is None:
2025-07-02 06:41:18.614 eqi, eqj = i, j
2025-07-02 06:41:18.614 continue
2025-07-02 06:41:18.614 cruncher.set_seq1(ai)
2025-07-02 06:41:18.614 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.614 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.614 # compares by a factor of 3.
2025-07-02 06:41:18.614 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.614 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.614 # of the computation is cached by cruncher
2025-07-02 06:41:18.614 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.614 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.614 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.614 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.614 if best_ratio < cutoff:
2025-07-02 06:41:18.614 # no non-identical "pretty close" pair
2025-07-02 06:41:18.615 if eqi is None:
2025-07-02 06:41:18.615 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.615 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.615 return
2025-07-02 06:41:18.615 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.615 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.615 else:
2025-07-02 06:41:18.615 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.615 eqi = None
2025-07-02 06:41:18.615
2025-07-02 06:41:18.615 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.615 # identical
2025-07-02 06:41:18.615
2025-07-02 06:41:18.615 # pump out diffs from before the synch point
2025-07-02 06:41:18.615 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.615
2025-07-02 06:41:18.615 # do intraline marking on the synch pair
2025-07-02 06:41:18.615 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.615 if eqi is None:
2025-07-02 06:41:18.616 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.616 atags = btags = ""
2025-07-02 06:41:18.616 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.616 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.616 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.616 if tag == 'replace':
2025-07-02 06:41:18.616 atags += '^' * la
2025-07-02 06:41:18.616 btags += '^' * lb
2025-07-02 06:41:18.616 elif tag == 'delete':
2025-07-02 06:41:18.616 atags += '-' * la
2025-07-02 06:41:18.616 elif tag == 'insert':
2025-07-02 06:41:18.616 btags += '+' * lb
2025-07-02 06:41:18.616 elif tag == 'equal':
2025-07-02 06:41:18.616 atags += ' ' * la
2025-07-02 06:41:18.616 btags += ' ' * lb
2025-07-02 06:41:18.616 else:
2025-07-02 06:41:18.616 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.616 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.616 else:
2025-07-02 06:41:18.616 # the synch pair is identical
2025-07-02 06:41:18.616 yield ' ' + aelt
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617 # pump out diffs from after the synch point
2025-07-02 06:41:18.617 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.617 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.617 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.617 alo = 430, ahi = 1101
2025-07-02 06:41:18.617 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.617 blo = 430, bhi = 1101
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.617 g = []
2025-07-02 06:41:18.617 if alo < ahi:
2025-07-02 06:41:18.617 if blo < bhi:
2025-07-02 06:41:18.617 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.617 else:
2025-07-02 06:41:18.618 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.618 elif blo < bhi:
2025-07-02 06:41:18.618 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 > yield from g
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.618 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.618 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.618 alo = 430, ahi = 1101
2025-07-02 06:41:18.618 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.618 blo = 430, bhi = 1101
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.618 r"""
2025-07-02 06:41:18.618 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.618 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.618 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.619 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619 Example:
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619 >>> d = Differ()
2025-07-02 06:41:18.619 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.619 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.619 >>> print(''.join(results), end="")
2025-07-02 06:41:18.619 - abcDefghiJkl
2025-07-02 06:41:18.619 + abcdefGhijkl
2025-07-02 06:41:18.619 """
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.619 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.619 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.619 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.619 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619 # search for the pair that matches best without being identical
2025-07-02 06:41:18.620 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.620 # on junk -- unless we have to)
2025-07-02 06:41:18.620 for j in range(blo, bhi):
2025-07-02 06:41:18.620 bj = b[j]
2025-07-02 06:41:18.620 cruncher.set_seq2(bj)
2025-07-02 06:41:18.620 for i in range(alo, ahi):
2025-07-02 06:41:18.620 ai = a[i]
2025-07-02 06:41:18.620 if ai == bj:
2025-07-02 06:41:18.620 if eqi is None:
2025-07-02 06:41:18.620 eqi, eqj = i, j
2025-07-02 06:41:18.620 continue
2025-07-02 06:41:18.620 cruncher.set_seq1(ai)
2025-07-02 06:41:18.620 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.620 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.620 # compares by a factor of 3.
2025-07-02 06:41:18.620 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.620 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.620 # of the computation is cached by cruncher
2025-07-02 06:41:18.620 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.620 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.621 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.621 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.621 if best_ratio < cutoff:
2025-07-02 06:41:18.621 # no non-identical "pretty close" pair
2025-07-02 06:41:18.621 if eqi is None:
2025-07-02 06:41:18.621 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.621 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.621 return
2025-07-02 06:41:18.621 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.621 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.621 else:
2025-07-02 06:41:18.621 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.621 eqi = None
2025-07-02 06:41:18.621
2025-07-02 06:41:18.621 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.621 # identical
2025-07-02 06:41:18.621
2025-07-02 06:41:18.621 # pump out diffs from before the synch point
2025-07-02 06:41:18.621 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.621
2025-07-02 06:41:18.621 # do intraline marking on the synch pair
2025-07-02 06:41:18.622 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.622 if eqi is None:
2025-07-02 06:41:18.622 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.622 atags = btags = ""
2025-07-02 06:41:18.622 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.622 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.622 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.622 if tag == 'replace':
2025-07-02 06:41:18.622 atags += '^' * la
2025-07-02 06:41:18.622 btags += '^' * lb
2025-07-02 06:41:18.622 elif tag == 'delete':
2025-07-02 06:41:18.622 atags += '-' * la
2025-07-02 06:41:18.622 elif tag == 'insert':
2025-07-02 06:41:18.622 btags += '+' * lb
2025-07-02 06:41:18.622 elif tag == 'equal':
2025-07-02 06:41:18.622 atags += ' ' * la
2025-07-02 06:41:18.622 btags += ' ' * lb
2025-07-02 06:41:18.622 else:
2025-07-02 06:41:18.622 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.622 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.623 else:
2025-07-02 06:41:18.623 # the synch pair is identical
2025-07-02 06:41:18.623 yield ' ' + aelt
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623 # pump out diffs from after the synch point
2025-07-02 06:41:18.623 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.623 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.623 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.623 alo = 431, ahi = 1101
2025-07-02 06:41:18.623 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.623 blo = 431, bhi = 1101
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.623 g = []
2025-07-02 06:41:18.623 if alo < ahi:
2025-07-02 06:41:18.623 if blo < bhi:
2025-07-02 06:41:18.624 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.624 else:
2025-07-02 06:41:18.624 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.624 elif blo < bhi:
2025-07-02 06:41:18.624 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.624
2025-07-02 06:41:18.624 > yield from g
2025-07-02 06:41:18.624
2025-07-02 06:41:18.624 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.624 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.624
2025-07-02 06:41:18.624 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.624 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.624 alo = 431, ahi = 1101
2025-07-02 06:41:18.624 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.624 blo = 431, bhi = 1101
2025-07-02 06:41:18.624
2025-07-02 06:41:18.625 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.625 r"""
2025-07-02 06:41:18.625 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.625 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.625 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.625 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.625
2025-07-02 06:41:18.625 Example:
2025-07-02 06:41:18.625
2025-07-02 06:41:18.625 >>> d = Differ()
2025-07-02 06:41:18.625 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.625 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.625 >>> print(''.join(results), end="")
2025-07-02 06:41:18.625 - abcDefghiJkl
2025-07-02 06:41:18.625 + abcdefGhijkl
2025-07-02 06:41:18.625 """
2025-07-02 06:41:18.625
2025-07-02 06:41:18.625 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.626 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.626 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.626 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.626 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.626
2025-07-02 06:41:18.626 # search for the pair that matches best without being identical
2025-07-02 06:41:18.626 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.626 # on junk -- unless we have to)
2025-07-02 06:41:18.626 for j in range(blo, bhi):
2025-07-02 06:41:18.626 bj = b[j]
2025-07-02 06:41:18.626 cruncher.set_seq2(bj)
2025-07-02 06:41:18.626 for i in range(alo, ahi):
2025-07-02 06:41:18.626 ai = a[i]
2025-07-02 06:41:18.626 if ai == bj:
2025-07-02 06:41:18.626 if eqi is None:
2025-07-02 06:41:18.626 eqi, eqj = i, j
2025-07-02 06:41:18.626 continue
2025-07-02 06:41:18.626 cruncher.set_seq1(ai)
2025-07-02 06:41:18.626 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.626 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.627 # compares by a factor of 3.
2025-07-02 06:41:18.627 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.627 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.627 # of the computation is cached by cruncher
2025-07-02 06:41:18.627 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.627 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.627 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.627 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.627 if best_ratio < cutoff:
2025-07-02 06:41:18.627 # no non-identical "pretty close" pair
2025-07-02 06:41:18.627 if eqi is None:
2025-07-02 06:41:18.627 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.627 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.627 return
2025-07-02 06:41:18.627 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.627 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.627 else:
2025-07-02 06:41:18.627 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.628 eqi = None
2025-07-02 06:41:18.628
2025-07-02 06:41:18.628 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.628 # identical
2025-07-02 06:41:18.628
2025-07-02 06:41:18.628 # pump out diffs from before the synch point
2025-07-02 06:41:18.628 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.628
2025-07-02 06:41:18.628 # do intraline marking on the synch pair
2025-07-02 06:41:18.628 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.628 if eqi is None:
2025-07-02 06:41:18.628 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.628 atags = btags = ""
2025-07-02 06:41:18.628 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.628 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.628 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.628 if tag == 'replace':
2025-07-02 06:41:18.628 atags += '^' * la
2025-07-02 06:41:18.628 btags += '^' * lb
2025-07-02 06:41:18.628 elif tag == 'delete':
2025-07-02 06:41:18.629 atags += '-' * la
2025-07-02 06:41:18.629 elif tag == 'insert':
2025-07-02 06:41:18.629 btags += '+' * lb
2025-07-02 06:41:18.629 elif tag == 'equal':
2025-07-02 06:41:18.629 atags += ' ' * la
2025-07-02 06:41:18.629 btags += ' ' * lb
2025-07-02 06:41:18.629 else:
2025-07-02 06:41:18.629 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.629 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.629 else:
2025-07-02 06:41:18.629 # the synch pair is identical
2025-07-02 06:41:18.629 yield ' ' + aelt
2025-07-02 06:41:18.629
2025-07-02 06:41:18.629 # pump out diffs from after the synch point
2025-07-02 06:41:18.629 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.629
2025-07-02 06:41:18.629 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.629 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.629
2025-07-02 06:41:18.629 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.630 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.630 alo = 432, ahi = 1101
2025-07-02 06:41:18.630 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.630 blo = 432, bhi = 1101
2025-07-02 06:41:18.630
2025-07-02 06:41:18.630 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.630 g = []
2025-07-02 06:41:18.630 if alo < ahi:
2025-07-02 06:41:18.630 if blo < bhi:
2025-07-02 06:41:18.630 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.630 else:
2025-07-02 06:41:18.630 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.630 elif blo < bhi:
2025-07-02 06:41:18.630 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.630
2025-07-02 06:41:18.630 > yield from g
2025-07-02 06:41:18.630
2025-07-02 06:41:18.630 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.630 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.630
2025-07-02 06:41:18.631 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.631 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.631 alo = 432, ahi = 1101
2025-07-02 06:41:18.631 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.631 blo = 432, bhi = 1101
2025-07-02 06:41:18.631
2025-07-02 06:41:18.631 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.631 r"""
2025-07-02 06:41:18.631 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.631 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.631 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.631 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.631
2025-07-02 06:41:18.631 Example:
2025-07-02 06:41:18.631
2025-07-02 06:41:18.631 >>> d = Differ()
2025-07-02 06:41:18.631 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.631 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.631 >>> print(''.join(results), end="")
2025-07-02 06:41:18.631 - abcDefghiJkl
2025-07-02 06:41:18.632 + abcdefGhijkl
2025-07-02 06:41:18.632 """
2025-07-02 06:41:18.632
2025-07-02 06:41:18.632 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.632 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.632 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.632 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.632 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.632
2025-07-02 06:41:18.632 # search for the pair that matches best without being identical
2025-07-02 06:41:18.632 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.632 # on junk -- unless we have to)
2025-07-02 06:41:18.632 for j in range(blo, bhi):
2025-07-02 06:41:18.632 bj = b[j]
2025-07-02 06:41:18.632 cruncher.set_seq2(bj)
2025-07-02 06:41:18.632 for i in range(alo, ahi):
2025-07-02 06:41:18.632 ai = a[i]
2025-07-02 06:41:18.633 if ai == bj:
2025-07-02 06:41:18.633 if eqi is None:
2025-07-02 06:41:18.633 eqi, eqj = i, j
2025-07-02 06:41:18.633 continue
2025-07-02 06:41:18.633 cruncher.set_seq1(ai)
2025-07-02 06:41:18.633 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.633 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.633 # compares by a factor of 3.
2025-07-02 06:41:18.633 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.633 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.633 # of the computation is cached by cruncher
2025-07-02 06:41:18.633 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.633 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.633 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.633 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.633 if best_ratio < cutoff:
2025-07-02 06:41:18.633 # no non-identical "pretty close" pair
2025-07-02 06:41:18.633 if eqi is None:
2025-07-02 06:41:18.633 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.634 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.634 return
2025-07-02 06:41:18.634 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.634 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.634 else:
2025-07-02 06:41:18.634 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.634 eqi = None
2025-07-02 06:41:18.634
2025-07-02 06:41:18.634 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.634 # identical
2025-07-02 06:41:18.634
2025-07-02 06:41:18.634 # pump out diffs from before the synch point
2025-07-02 06:41:18.634 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.634
2025-07-02 06:41:18.634 # do intraline marking on the synch pair
2025-07-02 06:41:18.634 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.634 if eqi is None:
2025-07-02 06:41:18.634 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.634 atags = btags = ""
2025-07-02 06:41:18.634 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.635 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.635 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.635 if tag == 'replace':
2025-07-02 06:41:18.635 atags += '^' * la
2025-07-02 06:41:18.635 btags += '^' * lb
2025-07-02 06:41:18.635 elif tag == 'delete':
2025-07-02 06:41:18.635 atags += '-' * la
2025-07-02 06:41:18.635 elif tag == 'insert':
2025-07-02 06:41:18.635 btags += '+' * lb
2025-07-02 06:41:18.635 elif tag == 'equal':
2025-07-02 06:41:18.635 atags += ' ' * la
2025-07-02 06:41:18.635 btags += ' ' * lb
2025-07-02 06:41:18.635 else:
2025-07-02 06:41:18.635 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.635 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.635 else:
2025-07-02 06:41:18.635 # the synch pair is identical
2025-07-02 06:41:18.635 yield ' ' + aelt
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636 # pump out diffs from after the synch point
2025-07-02 06:41:18.636 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.636 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.636 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.636 alo = 433, ahi = 1101
2025-07-02 06:41:18.636 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.636 blo = 433, bhi = 1101
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.636 g = []
2025-07-02 06:41:18.636 if alo < ahi:
2025-07-02 06:41:18.636 if blo < bhi:
2025-07-02 06:41:18.636 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.636 else:
2025-07-02 06:41:18.636 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.637 elif blo < bhi:
2025-07-02 06:41:18.637 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 > yield from g
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.637 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.637 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.637 alo = 433, ahi = 1101
2025-07-02 06:41:18.637 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.637 blo = 433, bhi = 1101
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.637 r"""
2025-07-02 06:41:18.637 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.637 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.637 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.637 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638 Example:
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638 >>> d = Differ()
2025-07-02 06:41:18.638 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.638 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.638 >>> print(''.join(results), end="")
2025-07-02 06:41:18.638 - abcDefghiJkl
2025-07-02 06:41:18.638 + abcdefGhijkl
2025-07-02 06:41:18.638 """
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.638 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.638 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.638 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.638 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638 # search for the pair that matches best without being identical
2025-07-02 06:41:18.639 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.639 # on junk -- unless we have to)
2025-07-02 06:41:18.639 for j in range(blo, bhi):
2025-07-02 06:41:18.639 bj = b[j]
2025-07-02 06:41:18.639 cruncher.set_seq2(bj)
2025-07-02 06:41:18.639 for i in range(alo, ahi):
2025-07-02 06:41:18.639 ai = a[i]
2025-07-02 06:41:18.639 if ai == bj:
2025-07-02 06:41:18.639 if eqi is None:
2025-07-02 06:41:18.639 eqi, eqj = i, j
2025-07-02 06:41:18.639 continue
2025-07-02 06:41:18.639 cruncher.set_seq1(ai)
2025-07-02 06:41:18.639 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.639 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.639 # compares by a factor of 3.
2025-07-02 06:41:18.639 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.639 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.639 # of the computation is cached by cruncher
2025-07-02 06:41:18.639 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.639 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.639 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.640 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.640 if best_ratio < cutoff:
2025-07-02 06:41:18.640 # no non-identical "pretty close" pair
2025-07-02 06:41:18.640 if eqi is None:
2025-07-02 06:41:18.640 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.640 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.640 return
2025-07-02 06:41:18.640 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.640 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.640 else:
2025-07-02 06:41:18.640 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.640 eqi = None
2025-07-02 06:41:18.640
2025-07-02 06:41:18.640 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.640 # identical
2025-07-02 06:41:18.640
2025-07-02 06:41:18.640 # pump out diffs from before the synch point
2025-07-02 06:41:18.640 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.640
2025-07-02 06:41:18.640 # do intraline marking on the synch pair
2025-07-02 06:41:18.641 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.641 if eqi is None:
2025-07-02 06:41:18.641 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.641 atags = btags = ""
2025-07-02 06:41:18.641 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.641 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.641 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.641 if tag == 'replace':
2025-07-02 06:41:18.641 atags += '^' * la
2025-07-02 06:41:18.641 btags += '^' * lb
2025-07-02 06:41:18.641 elif tag == 'delete':
2025-07-02 06:41:18.641 atags += '-' * la
2025-07-02 06:41:18.641 elif tag == 'insert':
2025-07-02 06:41:18.641 btags += '+' * lb
2025-07-02 06:41:18.641 elif tag == 'equal':
2025-07-02 06:41:18.641 atags += ' ' * la
2025-07-02 06:41:18.641 btags += ' ' * lb
2025-07-02 06:41:18.641 else:
2025-07-02 06:41:18.641 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.641 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.642 else:
2025-07-02 06:41:18.642 # the synch pair is identical
2025-07-02 06:41:18.642 yield ' ' + aelt
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642 # pump out diffs from after the synch point
2025-07-02 06:41:18.642 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.642 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.642 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.642 alo = 434, ahi = 1101
2025-07-02 06:41:18.642 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.642 blo = 434, bhi = 1101
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.643 g = []
2025-07-02 06:41:18.643 if alo < ahi:
2025-07-02 06:41:18.643 if blo < bhi:
2025-07-02 06:41:18.643 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.643 else:
2025-07-02 06:41:18.643 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.643 elif blo < bhi:
2025-07-02 06:41:18.643 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.643
2025-07-02 06:41:18.643 > yield from g
2025-07-02 06:41:18.643
2025-07-02 06:41:18.643 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.643 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.643
2025-07-02 06:41:18.643 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.643 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.643 alo = 434, ahi = 1101
2025-07-02 06:41:18.643 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.643 blo = 434, bhi = 1101
2025-07-02 06:41:18.644
2025-07-02 06:41:18.644 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.644 r"""
2025-07-02 06:41:18.644 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.644 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.644 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.644 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.644
2025-07-02 06:41:18.644 Example:
2025-07-02 06:41:18.644
2025-07-02 06:41:18.644 >>> d = Differ()
2025-07-02 06:41:18.644 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.644 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.644 >>> print(''.join(results), end="")
2025-07-02 06:41:18.644 - abcDefghiJkl
2025-07-02 06:41:18.644 + abcdefGhijkl
2025-07-02 06:41:18.644 """
2025-07-02 06:41:18.645
2025-07-02 06:41:18.645 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.645 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.645 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.645 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.645 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.645
2025-07-02 06:41:18.645 # search for the pair that matches best without being identical
2025-07-02 06:41:18.645 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.645 # on junk -- unless we have to)
2025-07-02 06:41:18.645 for j in range(blo, bhi):
2025-07-02 06:41:18.645 bj = b[j]
2025-07-02 06:41:18.645 cruncher.set_seq2(bj)
2025-07-02 06:41:18.645 for i in range(alo, ahi):
2025-07-02 06:41:18.645 ai = a[i]
2025-07-02 06:41:18.645 if ai == bj:
2025-07-02 06:41:18.645 if eqi is None:
2025-07-02 06:41:18.645 eqi, eqj = i, j
2025-07-02 06:41:18.645 continue
2025-07-02 06:41:18.645 cruncher.set_seq1(ai)
2025-07-02 06:41:18.646 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.646 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.646 # compares by a factor of 3.
2025-07-02 06:41:18.646 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.646 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.646 # of the computation is cached by cruncher
2025-07-02 06:41:18.646 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.646 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.646 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.646 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.646 if best_ratio < cutoff:
2025-07-02 06:41:18.646 # no non-identical "pretty close" pair
2025-07-02 06:41:18.646 if eqi is None:
2025-07-02 06:41:18.646 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.646 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.646 return
2025-07-02 06:41:18.646 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.646 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.646 else:
2025-07-02 06:41:18.647 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.647 eqi = None
2025-07-02 06:41:18.647
2025-07-02 06:41:18.647 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.647 # identical
2025-07-02 06:41:18.647
2025-07-02 06:41:18.647 # pump out diffs from before the synch point
2025-07-02 06:41:18.647 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.647
2025-07-02 06:41:18.647 # do intraline marking on the synch pair
2025-07-02 06:41:18.647 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.647 if eqi is None:
2025-07-02 06:41:18.647 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.647 atags = btags = ""
2025-07-02 06:41:18.647 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.647 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.647 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.647 if tag == 'replace':
2025-07-02 06:41:18.647 atags += '^' * la
2025-07-02 06:41:18.647 btags += '^' * lb
2025-07-02 06:41:18.648 elif tag == 'delete':
2025-07-02 06:41:18.648 atags += '-' * la
2025-07-02 06:41:18.648 elif tag == 'insert':
2025-07-02 06:41:18.648 btags += '+' * lb
2025-07-02 06:41:18.648 elif tag == 'equal':
2025-07-02 06:41:18.648 atags += ' ' * la
2025-07-02 06:41:18.648 btags += ' ' * lb
2025-07-02 06:41:18.648 else:
2025-07-02 06:41:18.648 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.648 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.648 else:
2025-07-02 06:41:18.648 # the synch pair is identical
2025-07-02 06:41:18.648 yield ' ' + aelt
2025-07-02 06:41:18.648
2025-07-02 06:41:18.648 # pump out diffs from after the synch point
2025-07-02 06:41:18.648 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.648
2025-07-02 06:41:18.648 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.648 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.648
2025-07-02 06:41:18.649 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.649 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.649 alo = 435, ahi = 1101
2025-07-02 06:41:18.649 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.649 blo = 435, bhi = 1101
2025-07-02 06:41:18.649
2025-07-02 06:41:18.649 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.649 g = []
2025-07-02 06:41:18.649 if alo < ahi:
2025-07-02 06:41:18.649 if blo < bhi:
2025-07-02 06:41:18.649 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.649 else:
2025-07-02 06:41:18.649 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.649 elif blo < bhi:
2025-07-02 06:41:18.649 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.649
2025-07-02 06:41:18.649 > yield from g
2025-07-02 06:41:18.649
2025-07-02 06:41:18.649 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.650 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.650 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.650 alo = 435, ahi = 1101
2025-07-02 06:41:18.650 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.650 blo = 435, bhi = 1101
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.650 r"""
2025-07-02 06:41:18.650 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.650 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.650 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.650 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650 Example:
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650 >>> d = Differ()
2025-07-02 06:41:18.651 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.651 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.651 >>> print(''.join(results), end="")
2025-07-02 06:41:18.651 - abcDefghiJkl
2025-07-02 06:41:18.651 + abcdefGhijkl
2025-07-02 06:41:18.651 """
2025-07-02 06:41:18.651
2025-07-02 06:41:18.651 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.651 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.651 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.651 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.651 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.651
2025-07-02 06:41:18.651 # search for the pair that matches best without being identical
2025-07-02 06:41:18.651 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.651 # on junk -- unless we have to)
2025-07-02 06:41:18.651 for j in range(blo, bhi):
2025-07-02 06:41:18.651 bj = b[j]
2025-07-02 06:41:18.652 cruncher.set_seq2(bj)
2025-07-02 06:41:18.652 for i in range(alo, ahi):
2025-07-02 06:41:18.652 ai = a[i]
2025-07-02 06:41:18.652 if ai == bj:
2025-07-02 06:41:18.652 if eqi is None:
2025-07-02 06:41:18.652 eqi, eqj = i, j
2025-07-02 06:41:18.652 continue
2025-07-02 06:41:18.652 cruncher.set_seq1(ai)
2025-07-02 06:41:18.652 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.652 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.652 # compares by a factor of 3.
2025-07-02 06:41:18.652 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.652 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.652 # of the computation is cached by cruncher
2025-07-02 06:41:18.652 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.652 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.652 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.652 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.652 if best_ratio < cutoff:
2025-07-02 06:41:18.652 # no non-identical "pretty close" pair
2025-07-02 06:41:18.653 if eqi is None:
2025-07-02 06:41:18.653 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.653 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.653 return
2025-07-02 06:41:18.653 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.653 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.653 else:
2025-07-02 06:41:18.653 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.653 eqi = None
2025-07-02 06:41:18.653
2025-07-02 06:41:18.653 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.653 # identical
2025-07-02 06:41:18.653
2025-07-02 06:41:18.653 # pump out diffs from before the synch point
2025-07-02 06:41:18.653 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.653
2025-07-02 06:41:18.653 # do intraline marking on the synch pair
2025-07-02 06:41:18.653 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.653 if eqi is None:
2025-07-02 06:41:18.653 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.654 atags = btags = ""
2025-07-02 06:41:18.654 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.654 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.654 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.654 if tag == 'replace':
2025-07-02 06:41:18.654 atags += '^' * la
2025-07-02 06:41:18.654 btags += '^' * lb
2025-07-02 06:41:18.654 elif tag == 'delete':
2025-07-02 06:41:18.654 atags += '-' * la
2025-07-02 06:41:18.654 elif tag == 'insert':
2025-07-02 06:41:18.654 btags += '+' * lb
2025-07-02 06:41:18.654 elif tag == 'equal':
2025-07-02 06:41:18.654 atags += ' ' * la
2025-07-02 06:41:18.654 btags += ' ' * lb
2025-07-02 06:41:18.654 else:
2025-07-02 06:41:18.654 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.654 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.654 else:
2025-07-02 06:41:18.654 # the synch pair is identical
2025-07-02 06:41:18.654 yield ' ' + aelt
2025-07-02 06:41:18.654
2025-07-02 06:41:18.655 # pump out diffs from after the synch point
2025-07-02 06:41:18.655 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.655
2025-07-02 06:41:18.655 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.655 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.655
2025-07-02 06:41:18.655 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.655 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.655 alo = 436, ahi = 1101
2025-07-02 06:41:18.655 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.655 blo = 436, bhi = 1101
2025-07-02 06:41:18.655
2025-07-02 06:41:18.655 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.655 g = []
2025-07-02 06:41:18.655 if alo < ahi:
2025-07-02 06:41:18.655 if blo < bhi:
2025-07-02 06:41:18.655 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.655 else:
2025-07-02 06:41:18.655 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.655 elif blo < bhi:
2025-07-02 06:41:18.656 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 > yield from g
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.656 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.656 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.656 alo = 436, ahi = 1101
2025-07-02 06:41:18.656 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.656 blo = 436, bhi = 1101
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.656 r"""
2025-07-02 06:41:18.656 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.656 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.656 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.656 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.656
2025-07-02 06:41:18.657 Example:
2025-07-02 06:41:18.657
2025-07-02 06:41:18.657 >>> d = Differ()
2025-07-02 06:41:18.657 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.657 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.657 >>> print(''.join(results), end="")
2025-07-02 06:41:18.657 - abcDefghiJkl
2025-07-02 06:41:18.657 + abcdefGhijkl
2025-07-02 06:41:18.657 """
2025-07-02 06:41:18.657
2025-07-02 06:41:18.657 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.657 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.657 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.657 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.657 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.658
2025-07-02 06:41:18.658 # search for the pair that matches best without being identical
2025-07-02 06:41:18.658 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.658 # on junk -- unless we have to)
2025-07-02 06:41:18.658 for j in range(blo, bhi):
2025-07-02 06:41:18.658 bj = b[j]
2025-07-02 06:41:18.658 cruncher.set_seq2(bj)
2025-07-02 06:41:18.658 for i in range(alo, ahi):
2025-07-02 06:41:18.658 ai = a[i]
2025-07-02 06:41:18.658 if ai == bj:
2025-07-02 06:41:18.658 if eqi is None:
2025-07-02 06:41:18.658 eqi, eqj = i, j
2025-07-02 06:41:18.658 continue
2025-07-02 06:41:18.658 cruncher.set_seq1(ai)
2025-07-02 06:41:18.658 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.658 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.658 # compares by a factor of 3.
2025-07-02 06:41:18.658 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.658 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.658 # of the computation is cached by cruncher
2025-07-02 06:41:18.659 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.659 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.659 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.659 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.659 if best_ratio < cutoff:
2025-07-02 06:41:18.659 # no non-identical "pretty close" pair
2025-07-02 06:41:18.659 if eqi is None:
2025-07-02 06:41:18.659 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.659 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.659 return
2025-07-02 06:41:18.659 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.659 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.659 else:
2025-07-02 06:41:18.659 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.659 eqi = None
2025-07-02 06:41:18.659
2025-07-02 06:41:18.659 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.660 # identical
2025-07-02 06:41:18.660
2025-07-02 06:41:18.660 # pump out diffs from before the synch point
2025-07-02 06:41:18.660 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.660
2025-07-02 06:41:18.660 # do intraline marking on the synch pair
2025-07-02 06:41:18.660 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.660 if eqi is None:
2025-07-02 06:41:18.660 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.660 atags = btags = ""
2025-07-02 06:41:18.660 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.660 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.660 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.660 if tag == 'replace':
2025-07-02 06:41:18.660 atags += '^' * la
2025-07-02 06:41:18.660 btags += '^' * lb
2025-07-02 06:41:18.660 elif tag == 'delete':
2025-07-02 06:41:18.660 atags += '-' * la
2025-07-02 06:41:18.660 elif tag == 'insert':
2025-07-02 06:41:18.660 btags += '+' * lb
2025-07-02 06:41:18.661 elif tag == 'equal':
2025-07-02 06:41:18.661 atags += ' ' * la
2025-07-02 06:41:18.661 btags += ' ' * lb
2025-07-02 06:41:18.661 else:
2025-07-02 06:41:18.661 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.661 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.661 else:
2025-07-02 06:41:18.661 # the synch pair is identical
2025-07-02 06:41:18.661 yield ' ' + aelt
2025-07-02 06:41:18.661
2025-07-02 06:41:18.661 # pump out diffs from after the synch point
2025-07-02 06:41:18.661 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.661
2025-07-02 06:41:18.661 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.661 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.661
2025-07-02 06:41:18.661 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.661 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.661 alo = 437, ahi = 1101
2025-07-02 06:41:18.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.662 blo = 437, bhi = 1101
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.662 g = []
2025-07-02 06:41:18.662 if alo < ahi:
2025-07-02 06:41:18.662 if blo < bhi:
2025-07-02 06:41:18.662 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.662 else:
2025-07-02 06:41:18.662 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.662 elif blo < bhi:
2025-07-02 06:41:18.662 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 > yield from g
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.662 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.662 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.662 alo = 437, ahi = 1101
2025-07-02 06:41:18.663 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.663 blo = 437, bhi = 1101
2025-07-02 06:41:18.663
2025-07-02 06:41:18.663 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.663 r"""
2025-07-02 06:41:18.663 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.663 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.663 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.663 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.663
2025-07-02 06:41:18.663 Example:
2025-07-02 06:41:18.663
2025-07-02 06:41:18.663 >>> d = Differ()
2025-07-02 06:41:18.663 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.663 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.663 >>> print(''.join(results), end="")
2025-07-02 06:41:18.663 - abcDefghiJkl
2025-07-02 06:41:18.663 + abcdefGhijkl
2025-07-02 06:41:18.664 """
2025-07-02 06:41:18.664
2025-07-02 06:41:18.664 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.664 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.664 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.664 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.664 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.664
2025-07-02 06:41:18.664 # search for the pair that matches best without being identical
2025-07-02 06:41:18.664 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.664 # on junk -- unless we have to)
2025-07-02 06:41:18.664 for j in range(blo, bhi):
2025-07-02 06:41:18.664 bj = b[j]
2025-07-02 06:41:18.664 cruncher.set_seq2(bj)
2025-07-02 06:41:18.664 for i in range(alo, ahi):
2025-07-02 06:41:18.664 ai = a[i]
2025-07-02 06:41:18.664 if ai == bj:
2025-07-02 06:41:18.664 if eqi is None:
2025-07-02 06:41:18.664 eqi, eqj = i, j
2025-07-02 06:41:18.664 continue
2025-07-02 06:41:18.664 cruncher.set_seq1(ai)
2025-07-02 06:41:18.665 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.665 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.665 # compares by a factor of 3.
2025-07-02 06:41:18.665 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.665 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.665 # of the computation is cached by cruncher
2025-07-02 06:41:18.665 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.665 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.665 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.665 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.665 if best_ratio < cutoff:
2025-07-02 06:41:18.665 # no non-identical "pretty close" pair
2025-07-02 06:41:18.665 if eqi is None:
2025-07-02 06:41:18.665 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.665 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.665 return
2025-07-02 06:41:18.665 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.665 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.665 else:
2025-07-02 06:41:18.665 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.666 eqi = None
2025-07-02 06:41:18.666
2025-07-02 06:41:18.666 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.666 # identical
2025-07-02 06:41:18.666
2025-07-02 06:41:18.666 # pump out diffs from before the synch point
2025-07-02 06:41:18.666 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.666
2025-07-02 06:41:18.666 # do intraline marking on the synch pair
2025-07-02 06:41:18.666 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.666 if eqi is None:
2025-07-02 06:41:18.666 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.666 atags = btags = ""
2025-07-02 06:41:18.666 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.666 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.666 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.666 if tag == 'replace':
2025-07-02 06:41:18.666 atags += '^' * la
2025-07-02 06:41:18.666 btags += '^' * lb
2025-07-02 06:41:18.666 elif tag == 'delete':
2025-07-02 06:41:18.666 atags += '-' * la
2025-07-02 06:41:18.667 elif tag == 'insert':
2025-07-02 06:41:18.667 btags += '+' * lb
2025-07-02 06:41:18.667 elif tag == 'equal':
2025-07-02 06:41:18.667 atags += ' ' * la
2025-07-02 06:41:18.667 btags += ' ' * lb
2025-07-02 06:41:18.667 else:
2025-07-02 06:41:18.667 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.667 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.667 else:
2025-07-02 06:41:18.667 # the synch pair is identical
2025-07-02 06:41:18.667 yield ' ' + aelt
2025-07-02 06:41:18.667
2025-07-02 06:41:18.667 # pump out diffs from after the synch point
2025-07-02 06:41:18.667 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.667
2025-07-02 06:41:18.667 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.667
2025-07-02 06:41:18.667 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.668 alo = 438, ahi = 1101
2025-07-02 06:41:18.668 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.668 blo = 438, bhi = 1101
2025-07-02 06:41:18.668
2025-07-02 06:41:18.668 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.668 g = []
2025-07-02 06:41:18.668 if alo < ahi:
2025-07-02 06:41:18.668 if blo < bhi:
2025-07-02 06:41:18.668 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.668 else:
2025-07-02 06:41:18.668 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.668 elif blo < bhi:
2025-07-02 06:41:18.668 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.668
2025-07-02 06:41:18.668 > yield from g
2025-07-02 06:41:18.668
2025-07-02 06:41:18.668 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.668 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.669 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.669 alo = 438, ahi = 1101
2025-07-02 06:41:18.669 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.669 blo = 438, bhi = 1101
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.669 r"""
2025-07-02 06:41:18.669 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.669 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.669 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.669 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669 Example:
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669 >>> d = Differ()
2025-07-02 06:41:18.669 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.669 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.670 >>> print(''.join(results), end="")
2025-07-02 06:41:18.670 - abcDefghiJkl
2025-07-02 06:41:18.670 + abcdefGhijkl
2025-07-02 06:41:18.670 """
2025-07-02 06:41:18.670
2025-07-02 06:41:18.670 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.670 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.670 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.670 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.670 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.670
2025-07-02 06:41:18.670 # search for the pair that matches best without being identical
2025-07-02 06:41:18.670 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.670 # on junk -- unless we have to)
2025-07-02 06:41:18.670 for j in range(blo, bhi):
2025-07-02 06:41:18.670 bj = b[j]
2025-07-02 06:41:18.670 cruncher.set_seq2(bj)
2025-07-02 06:41:18.670 for i in range(alo, ahi):
2025-07-02 06:41:18.671 ai = a[i]
2025-07-02 06:41:18.671 if ai == bj:
2025-07-02 06:41:18.671 if eqi is None:
2025-07-02 06:41:18.671 eqi, eqj = i, j
2025-07-02 06:41:18.671 continue
2025-07-02 06:41:18.671 cruncher.set_seq1(ai)
2025-07-02 06:41:18.671 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.671 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.671 # compares by a factor of 3.
2025-07-02 06:41:18.671 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.671 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.671 # of the computation is cached by cruncher
2025-07-02 06:41:18.671 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.671 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.671 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.671 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.671 if best_ratio < cutoff:
2025-07-02 06:41:18.671 # no non-identical "pretty close" pair
2025-07-02 06:41:18.671 if eqi is None:
2025-07-02 06:41:18.671 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.671 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.672 return
2025-07-02 06:41:18.672 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.672 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.672 else:
2025-07-02 06:41:18.672 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.672 eqi = None
2025-07-02 06:41:18.672
2025-07-02 06:41:18.672 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.672 # identical
2025-07-02 06:41:18.672
2025-07-02 06:41:18.672 # pump out diffs from before the synch point
2025-07-02 06:41:18.672 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.672
2025-07-02 06:41:18.672 # do intraline marking on the synch pair
2025-07-02 06:41:18.672 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.672 if eqi is None:
2025-07-02 06:41:18.672 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.672 atags = btags = ""
2025-07-02 06:41:18.672 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.672 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.673 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.673 if tag == 'replace':
2025-07-02 06:41:18.673 atags += '^' * la
2025-07-02 06:41:18.673 btags += '^' * lb
2025-07-02 06:41:18.673 elif tag == 'delete':
2025-07-02 06:41:18.673 atags += '-' * la
2025-07-02 06:41:18.673 elif tag == 'insert':
2025-07-02 06:41:18.673 btags += '+' * lb
2025-07-02 06:41:18.673 elif tag == 'equal':
2025-07-02 06:41:18.673 atags += ' ' * la
2025-07-02 06:41:18.673 btags += ' ' * lb
2025-07-02 06:41:18.673 else:
2025-07-02 06:41:18.673 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.673 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.673 else:
2025-07-02 06:41:18.673 # the synch pair is identical
2025-07-02 06:41:18.673 yield ' ' + aelt
2025-07-02 06:41:18.673
2025-07-02 06:41:18.674 # pump out diffs from after the synch point
2025-07-02 06:41:18.674 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.674
2025-07-02 06:41:18.674 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.674 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.674
2025-07-02 06:41:18.674 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.674 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.674 alo = 439, ahi = 1101
2025-07-02 06:41:18.674 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.674 blo = 439, bhi = 1101
2025-07-02 06:41:18.674
2025-07-02 06:41:18.674 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.674 g = []
2025-07-02 06:41:18.674 if alo < ahi:
2025-07-02 06:41:18.674 if blo < bhi:
2025-07-02 06:41:18.674 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.674 else:
2025-07-02 06:41:18.674 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.675 elif blo < bhi:
2025-07-02 06:41:18.675 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 > yield from g
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.675 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.675 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.675 alo = 439, ahi = 1101
2025-07-02 06:41:18.675 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.675 blo = 439, bhi = 1101
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.675 r"""
2025-07-02 06:41:18.675 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.675 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.675 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.675 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.676
2025-07-02 06:41:18.676 Example:
2025-07-02 06:41:18.676
2025-07-02 06:41:18.676 >>> d = Differ()
2025-07-02 06:41:18.676 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.676 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.676 >>> print(''.join(results), end="")
2025-07-02 06:41:18.676 - abcDefghiJkl
2025-07-02 06:41:18.676 + abcdefGhijkl
2025-07-02 06:41:18.676 """
2025-07-02 06:41:18.676
2025-07-02 06:41:18.676 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.676 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.676 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.676 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.676 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.676
2025-07-02 06:41:18.677 # search for the pair that matches best without being identical
2025-07-02 06:41:18.677 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.677 # on junk -- unless we have to)
2025-07-02 06:41:18.677 for j in range(blo, bhi):
2025-07-02 06:41:18.677 bj = b[j]
2025-07-02 06:41:18.677 cruncher.set_seq2(bj)
2025-07-02 06:41:18.677 for i in range(alo, ahi):
2025-07-02 06:41:18.677 ai = a[i]
2025-07-02 06:41:18.677 if ai == bj:
2025-07-02 06:41:18.677 if eqi is None:
2025-07-02 06:41:18.677 eqi, eqj = i, j
2025-07-02 06:41:18.677 continue
2025-07-02 06:41:18.677 cruncher.set_seq1(ai)
2025-07-02 06:41:18.677 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.677 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.677 # compares by a factor of 3.
2025-07-02 06:41:18.677 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.677 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.677 # of the computation is cached by cruncher
2025-07-02 06:41:18.677 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.678 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.678 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.678 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.678 if best_ratio < cutoff:
2025-07-02 06:41:18.678 # no non-identical "pretty close" pair
2025-07-02 06:41:18.678 if eqi is None:
2025-07-02 06:41:18.678 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.678 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.678 return
2025-07-02 06:41:18.678 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.678 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.678 else:
2025-07-02 06:41:18.678 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.678 eqi = None
2025-07-02 06:41:18.678
2025-07-02 06:41:18.678 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.678 # identical
2025-07-02 06:41:18.678
2025-07-02 06:41:18.678 # pump out diffs from before the synch point
2025-07-02 06:41:18.679 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.679
2025-07-02 06:41:18.679 # do intraline marking on the synch pair
2025-07-02 06:41:18.679 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.679 if eqi is None:
2025-07-02 06:41:18.679 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.679 atags = btags = ""
2025-07-02 06:41:18.679 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.679 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.679 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.679 if tag == 'replace':
2025-07-02 06:41:18.679 atags += '^' * la
2025-07-02 06:41:18.679 btags += '^' * lb
2025-07-02 06:41:18.679 elif tag == 'delete':
2025-07-02 06:41:18.679 atags += '-' * la
2025-07-02 06:41:18.679 elif tag == 'insert':
2025-07-02 06:41:18.679 btags += '+' * lb
2025-07-02 06:41:18.679 elif tag == 'equal':
2025-07-02 06:41:18.679 atags += ' ' * la
2025-07-02 06:41:18.679 btags += ' ' * lb
2025-07-02 06:41:18.679 else:
2025-07-02 06:41:18.680 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.680 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.680 else:
2025-07-02 06:41:18.680 # the synch pair is identical
2025-07-02 06:41:18.680 yield ' ' + aelt
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680 # pump out diffs from after the synch point
2025-07-02 06:41:18.680 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.680 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.680 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.680 alo = 440, ahi = 1101
2025-07-02 06:41:18.680 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.680 blo = 440, bhi = 1101
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.680 g = []
2025-07-02 06:41:18.681 if alo < ahi:
2025-07-02 06:41:18.681 if blo < bhi:
2025-07-02 06:41:18.681 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.681 else:
2025-07-02 06:41:18.681 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.681 elif blo < bhi:
2025-07-02 06:41:18.681 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 > yield from g
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.681 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.681 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.681 alo = 440, ahi = 1101
2025-07-02 06:41:18.681 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.681 blo = 440, bhi = 1101
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.682 r"""
2025-07-02 06:41:18.682 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.682 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.682 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.682 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.682
2025-07-02 06:41:18.682 Example:
2025-07-02 06:41:18.682
2025-07-02 06:41:18.682 >>> d = Differ()
2025-07-02 06:41:18.682 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.682 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.682 >>> print(''.join(results), end="")
2025-07-02 06:41:18.682 - abcDefghiJkl
2025-07-02 06:41:18.682 + abcdefGhijkl
2025-07-02 06:41:18.682 """
2025-07-02 06:41:18.682
2025-07-02 06:41:18.682 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.682 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.683 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.683 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.683 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.683
2025-07-02 06:41:18.683 # search for the pair that matches best without being identical
2025-07-02 06:41:18.683 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.683 # on junk -- unless we have to)
2025-07-02 06:41:18.683 for j in range(blo, bhi):
2025-07-02 06:41:18.683 bj = b[j]
2025-07-02 06:41:18.683 cruncher.set_seq2(bj)
2025-07-02 06:41:18.683 for i in range(alo, ahi):
2025-07-02 06:41:18.683 ai = a[i]
2025-07-02 06:41:18.683 if ai == bj:
2025-07-02 06:41:18.683 if eqi is None:
2025-07-02 06:41:18.683 eqi, eqj = i, j
2025-07-02 06:41:18.683 continue
2025-07-02 06:41:18.683 cruncher.set_seq1(ai)
2025-07-02 06:41:18.683 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.683 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.683 # compares by a factor of 3.
2025-07-02 06:41:18.683 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.684 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.684 # of the computation is cached by cruncher
2025-07-02 06:41:18.684 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.684 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.684 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.684 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.684 if best_ratio < cutoff:
2025-07-02 06:41:18.684 # no non-identical "pretty close" pair
2025-07-02 06:41:18.684 if eqi is None:
2025-07-02 06:41:18.684 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.684 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.684 return
2025-07-02 06:41:18.684 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.684 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.684 else:
2025-07-02 06:41:18.684 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.684 eqi = None
2025-07-02 06:41:18.684
2025-07-02 06:41:18.684 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.684 # identical
2025-07-02 06:41:18.685
2025-07-02 06:41:18.685 # pump out diffs from before the synch point
2025-07-02 06:41:18.685 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.685
2025-07-02 06:41:18.685 # do intraline marking on the synch pair
2025-07-02 06:41:18.685 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.685 if eqi is None:
2025-07-02 06:41:18.685 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.685 atags = btags = ""
2025-07-02 06:41:18.685 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.685 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.685 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.685 if tag == 'replace':
2025-07-02 06:41:18.685 atags += '^' * la
2025-07-02 06:41:18.685 btags += '^' * lb
2025-07-02 06:41:18.685 elif tag == 'delete':
2025-07-02 06:41:18.685 atags += '-' * la
2025-07-02 06:41:18.685 elif tag == 'insert':
2025-07-02 06:41:18.685 btags += '+' * lb
2025-07-02 06:41:18.686 elif tag == 'equal':
2025-07-02 06:41:18.686 atags += ' ' * la
2025-07-02 06:41:18.686 btags += ' ' * lb
2025-07-02 06:41:18.686 else:
2025-07-02 06:41:18.686 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.686 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.686 else:
2025-07-02 06:41:18.686 # the synch pair is identical
2025-07-02 06:41:18.686 yield ' ' + aelt
2025-07-02 06:41:18.686
2025-07-02 06:41:18.686 # pump out diffs from after the synch point
2025-07-02 06:41:18.686 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.686
2025-07-02 06:41:18.686 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.686 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.686
2025-07-02 06:41:18.686 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.686 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.686 alo = 441, ahi = 1101
2025-07-02 06:41:18.686 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.687 blo = 441, bhi = 1101
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.687 g = []
2025-07-02 06:41:18.687 if alo < ahi:
2025-07-02 06:41:18.687 if blo < bhi:
2025-07-02 06:41:18.687 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.687 else:
2025-07-02 06:41:18.687 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.687 elif blo < bhi:
2025-07-02 06:41:18.687 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 > yield from g
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.687 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.687 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.688 alo = 441, ahi = 1101
2025-07-02 06:41:18.688 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.688 blo = 441, bhi = 1101
2025-07-02 06:41:18.688
2025-07-02 06:41:18.688 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.688 r"""
2025-07-02 06:41:18.688 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.688 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.688 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.688 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.688
2025-07-02 06:41:18.688 Example:
2025-07-02 06:41:18.688
2025-07-02 06:41:18.688 >>> d = Differ()
2025-07-02 06:41:18.688 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.688 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.688 >>> print(''.join(results), end="")
2025-07-02 06:41:18.688 - abcDefghiJkl
2025-07-02 06:41:18.688 + abcdefGhijkl
2025-07-02 06:41:18.689 """
2025-07-02 06:41:18.689
2025-07-02 06:41:18.689 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.689 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.689 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.689 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.689 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.689
2025-07-02 06:41:18.689 # search for the pair that matches best without being identical
2025-07-02 06:41:18.689 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.689 # on junk -- unless we have to)
2025-07-02 06:41:18.689 for j in range(blo, bhi):
2025-07-02 06:41:18.689 bj = b[j]
2025-07-02 06:41:18.689 cruncher.set_seq2(bj)
2025-07-02 06:41:18.689 for i in range(alo, ahi):
2025-07-02 06:41:18.689 ai = a[i]
2025-07-02 06:41:18.689 if ai == bj:
2025-07-02 06:41:18.690 if eqi is None:
2025-07-02 06:41:18.690 eqi, eqj = i, j
2025-07-02 06:41:18.690 continue
2025-07-02 06:41:18.690 cruncher.set_seq1(ai)
2025-07-02 06:41:18.690 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.690 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.690 # compares by a factor of 3.
2025-07-02 06:41:18.690 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.690 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.690 # of the computation is cached by cruncher
2025-07-02 06:41:18.690 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.690 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.690 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.690 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.690 if best_ratio < cutoff:
2025-07-02 06:41:18.690 # no non-identical "pretty close" pair
2025-07-02 06:41:18.690 if eqi is None:
2025-07-02 06:41:18.690 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.690 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.690 return
2025-07-02 06:41:18.691 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.691 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.691 else:
2025-07-02 06:41:18.691 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.691 eqi = None
2025-07-02 06:41:18.691
2025-07-02 06:41:18.691 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.691 # identical
2025-07-02 06:41:18.691
2025-07-02 06:41:18.691 # pump out diffs from before the synch point
2025-07-02 06:41:18.691 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.691
2025-07-02 06:41:18.691 # do intraline marking on the synch pair
2025-07-02 06:41:18.691 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.691 if eqi is None:
2025-07-02 06:41:18.691 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.691 atags = btags = ""
2025-07-02 06:41:18.691 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.691 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.691 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.692 if tag == 'replace':
2025-07-02 06:41:18.692 atags += '^' * la
2025-07-02 06:41:18.692 btags += '^' * lb
2025-07-02 06:41:18.692 elif tag == 'delete':
2025-07-02 06:41:18.692 atags += '-' * la
2025-07-02 06:41:18.692 elif tag == 'insert':
2025-07-02 06:41:18.692 btags += '+' * lb
2025-07-02 06:41:18.692 elif tag == 'equal':
2025-07-02 06:41:18.692 atags += ' ' * la
2025-07-02 06:41:18.692 btags += ' ' * lb
2025-07-02 06:41:18.692 else:
2025-07-02 06:41:18.692 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.692 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.692 else:
2025-07-02 06:41:18.692 # the synch pair is identical
2025-07-02 06:41:18.692 yield ' ' + aelt
2025-07-02 06:41:18.692
2025-07-02 06:41:18.692 # pump out diffs from after the synch point
2025-07-02 06:41:18.692 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.692
2025-07-02 06:41:18.692 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.693 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.693
2025-07-02 06:41:18.693 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.693 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.693 alo = 444, ahi = 1101
2025-07-02 06:41:18.693 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.693 blo = 444, bhi = 1101
2025-07-02 06:41:18.693
2025-07-02 06:41:18.693 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.693 g = []
2025-07-02 06:41:18.693 if alo < ahi:
2025-07-02 06:41:18.693 if blo < bhi:
2025-07-02 06:41:18.693 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.693 else:
2025-07-02 06:41:18.693 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.693 elif blo < bhi:
2025-07-02 06:41:18.693 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.693
2025-07-02 06:41:18.693 > yield from g
2025-07-02 06:41:18.693
2025-07-02 06:41:18.694 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.694 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.694
2025-07-02 06:41:18.694 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.694 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.694 alo = 444, ahi = 1101
2025-07-02 06:41:18.694 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.694 blo = 444, bhi = 1101
2025-07-02 06:41:18.694
2025-07-02 06:41:18.694 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.694 r"""
2025-07-02 06:41:18.694 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.694 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.694 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.694 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.694
2025-07-02 06:41:18.694 Example:
2025-07-02 06:41:18.694
2025-07-02 06:41:18.695 >>> d = Differ()
2025-07-02 06:41:18.695 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.695 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.695 >>> print(''.join(results), end="")
2025-07-02 06:41:18.695 - abcDefghiJkl
2025-07-02 06:41:18.695 + abcdefGhijkl
2025-07-02 06:41:18.695 """
2025-07-02 06:41:18.695
2025-07-02 06:41:18.695 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.695 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.695 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.695 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.695 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.695
2025-07-02 06:41:18.695 # search for the pair that matches best without being identical
2025-07-02 06:41:18.695 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.695 # on junk -- unless we have to)
2025-07-02 06:41:18.696 for j in range(blo, bhi):
2025-07-02 06:41:18.696 bj = b[j]
2025-07-02 06:41:18.696 cruncher.set_seq2(bj)
2025-07-02 06:41:18.696 for i in range(alo, ahi):
2025-07-02 06:41:18.696 ai = a[i]
2025-07-02 06:41:18.696 if ai == bj:
2025-07-02 06:41:18.696 if eqi is None:
2025-07-02 06:41:18.696 eqi, eqj = i, j
2025-07-02 06:41:18.696 continue
2025-07-02 06:41:18.696 cruncher.set_seq1(ai)
2025-07-02 06:41:18.696 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.696 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.696 # compares by a factor of 3.
2025-07-02 06:41:18.696 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.696 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.696 # of the computation is cached by cruncher
2025-07-02 06:41:18.696 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.696 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.696 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.696 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.697 if best_ratio < cutoff:
2025-07-02 06:41:18.697 # no non-identical "pretty close" pair
2025-07-02 06:41:18.697 if eqi is None:
2025-07-02 06:41:18.697 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.697 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.697 return
2025-07-02 06:41:18.697 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.697 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.697 else:
2025-07-02 06:41:18.697 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.697 eqi = None
2025-07-02 06:41:18.697
2025-07-02 06:41:18.697 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.697 # identical
2025-07-02 06:41:18.697
2025-07-02 06:41:18.697 # pump out diffs from before the synch point
2025-07-02 06:41:18.697 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.697
2025-07-02 06:41:18.697 # do intraline marking on the synch pair
2025-07-02 06:41:18.697 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.698 if eqi is None:
2025-07-02 06:41:18.698 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.698 atags = btags = ""
2025-07-02 06:41:18.698 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.698 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.698 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.698 if tag == 'replace':
2025-07-02 06:41:18.698 atags += '^' * la
2025-07-02 06:41:18.698 btags += '^' * lb
2025-07-02 06:41:18.698 elif tag == 'delete':
2025-07-02 06:41:18.698 atags += '-' * la
2025-07-02 06:41:18.698 elif tag == 'insert':
2025-07-02 06:41:18.698 btags += '+' * lb
2025-07-02 06:41:18.698 elif tag == 'equal':
2025-07-02 06:41:18.698 atags += ' ' * la
2025-07-02 06:41:18.698 btags += ' ' * lb
2025-07-02 06:41:18.698 else:
2025-07-02 06:41:18.698 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.698 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.698 else:
2025-07-02 06:41:18.698 # the synch pair is identical
2025-07-02 06:41:18.699 yield ' ' + aelt
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699 # pump out diffs from after the synch point
2025-07-02 06:41:18.699 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.699 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.699 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.699 alo = 445, ahi = 1101
2025-07-02 06:41:18.699 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.699 blo = 445, bhi = 1101
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.699 g = []
2025-07-02 06:41:18.699 if alo < ahi:
2025-07-02 06:41:18.699 if blo < bhi:
2025-07-02 06:41:18.699 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.699 else:
2025-07-02 06:41:18.700 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.700 elif blo < bhi:
2025-07-02 06:41:18.700 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 > yield from g
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.700 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.700 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.700 alo = 445, ahi = 1101
2025-07-02 06:41:18.700 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.700 blo = 445, bhi = 1101
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.700 r"""
2025-07-02 06:41:18.700 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.700 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.700 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.701 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.701
2025-07-02 06:41:18.701 Example:
2025-07-02 06:41:18.701
2025-07-02 06:41:18.701 >>> d = Differ()
2025-07-02 06:41:18.701 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.701 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.701 >>> print(''.join(results), end="")
2025-07-02 06:41:18.701 - abcDefghiJkl
2025-07-02 06:41:18.701 + abcdefGhijkl
2025-07-02 06:41:18.701 """
2025-07-02 06:41:18.701
2025-07-02 06:41:18.701 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.701 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.701 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.701 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.701 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.701
2025-07-02 06:41:18.702 # search for the pair that matches best without being identical
2025-07-02 06:41:18.702 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.702 # on junk -- unless we have to)
2025-07-02 06:41:18.702 for j in range(blo, bhi):
2025-07-02 06:41:18.702 bj = b[j]
2025-07-02 06:41:18.702 cruncher.set_seq2(bj)
2025-07-02 06:41:18.702 for i in range(alo, ahi):
2025-07-02 06:41:18.702 ai = a[i]
2025-07-02 06:41:18.702 if ai == bj:
2025-07-02 06:41:18.702 if eqi is None:
2025-07-02 06:41:18.702 eqi, eqj = i, j
2025-07-02 06:41:18.702 continue
2025-07-02 06:41:18.702 cruncher.set_seq1(ai)
2025-07-02 06:41:18.702 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.702 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.702 # compares by a factor of 3.
2025-07-02 06:41:18.702 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.702 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.702 # of the computation is cached by cruncher
2025-07-02 06:41:18.703 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.703 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.703 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.703 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.703 if best_ratio < cutoff:
2025-07-02 06:41:18.703 # no non-identical "pretty close" pair
2025-07-02 06:41:18.703 if eqi is None:
2025-07-02 06:41:18.703 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.703 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.703 return
2025-07-02 06:41:18.703 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.703 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.703 else:
2025-07-02 06:41:18.703 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.703 eqi = None
2025-07-02 06:41:18.703
2025-07-02 06:41:18.703 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.703 # identical
2025-07-02 06:41:18.703
2025-07-02 06:41:18.704 # pump out diffs from before the synch point
2025-07-02 06:41:18.704 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.704
2025-07-02 06:41:18.704 # do intraline marking on the synch pair
2025-07-02 06:41:18.704 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.704 if eqi is None:
2025-07-02 06:41:18.704 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.704 atags = btags = ""
2025-07-02 06:41:18.704 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.704 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.704 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.704 if tag == 'replace':
2025-07-02 06:41:18.704 atags += '^' * la
2025-07-02 06:41:18.704 btags += '^' * lb
2025-07-02 06:41:18.704 elif tag == 'delete':
2025-07-02 06:41:18.704 atags += '-' * la
2025-07-02 06:41:18.704 elif tag == 'insert':
2025-07-02 06:41:18.704 btags += '+' * lb
2025-07-02 06:41:18.704 elif tag == 'equal':
2025-07-02 06:41:18.704 atags += ' ' * la
2025-07-02 06:41:18.705 btags += ' ' * lb
2025-07-02 06:41:18.705 else:
2025-07-02 06:41:18.705 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.705 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.705 else:
2025-07-02 06:41:18.705 # the synch pair is identical
2025-07-02 06:41:18.705 yield ' ' + aelt
2025-07-02 06:41:18.705
2025-07-02 06:41:18.705 # pump out diffs from after the synch point
2025-07-02 06:41:18.705 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.705
2025-07-02 06:41:18.705 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.705 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.705
2025-07-02 06:41:18.705 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.705 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.705 alo = 446, ahi = 1101
2025-07-02 06:41:18.706 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.706 blo = 446, bhi = 1101
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.706 g = []
2025-07-02 06:41:18.706 if alo < ahi:
2025-07-02 06:41:18.706 if blo < bhi:
2025-07-02 06:41:18.706 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.706 else:
2025-07-02 06:41:18.706 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.706 elif blo < bhi:
2025-07-02 06:41:18.706 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 > yield from g
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.706 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.707 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.707 alo = 446, ahi = 1101
2025-07-02 06:41:18.707 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.707 blo = 446, bhi = 1101
2025-07-02 06:41:18.707
2025-07-02 06:41:18.707 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.707 r"""
2025-07-02 06:41:18.707 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.707 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.707 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.707 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.707
2025-07-02 06:41:18.707 Example:
2025-07-02 06:41:18.707
2025-07-02 06:41:18.707 >>> d = Differ()
2025-07-02 06:41:18.707 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.707 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.708 >>> print(''.join(results), end="")
2025-07-02 06:41:18.708 - abcDefghiJkl
2025-07-02 06:41:18.708 + abcdefGhijkl
2025-07-02 06:41:18.708 """
2025-07-02 06:41:18.708
2025-07-02 06:41:18.708 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.708 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.708 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.708 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.708 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.708
2025-07-02 06:41:18.708 # search for the pair that matches best without being identical
2025-07-02 06:41:18.708 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.708 # on junk -- unless we have to)
2025-07-02 06:41:18.709 for j in range(blo, bhi):
2025-07-02 06:41:18.709 bj = b[j]
2025-07-02 06:41:18.709 cruncher.set_seq2(bj)
2025-07-02 06:41:18.709 for i in range(alo, ahi):
2025-07-02 06:41:18.709 ai = a[i]
2025-07-02 06:41:18.709 if ai == bj:
2025-07-02 06:41:18.709 if eqi is None:
2025-07-02 06:41:18.709 eqi, eqj = i, j
2025-07-02 06:41:18.709 continue
2025-07-02 06:41:18.709 cruncher.set_seq1(ai)
2025-07-02 06:41:18.709 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.709 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.709 # compares by a factor of 3.
2025-07-02 06:41:18.709 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.709 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.710 # of the computation is cached by cruncher
2025-07-02 06:41:18.710 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.710 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.710 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.710 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.710 if best_ratio < cutoff:
2025-07-02 06:41:18.710 # no non-identical "pretty close" pair
2025-07-02 06:41:18.710 if eqi is None:
2025-07-02 06:41:18.710 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.710 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.710 return
2025-07-02 06:41:18.710 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.710 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.710 else:
2025-07-02 06:41:18.710 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.710 eqi = None
2025-07-02 06:41:18.711
2025-07-02 06:41:18.711 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.711 # identical
2025-07-02 06:41:18.711
2025-07-02 06:41:18.711 # pump out diffs from before the synch point
2025-07-02 06:41:18.711 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.711
2025-07-02 06:41:18.711 # do intraline marking on the synch pair
2025-07-02 06:41:18.711 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.711 if eqi is None:
2025-07-02 06:41:18.711 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.711 atags = btags = ""
2025-07-02 06:41:18.711 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.711 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.711 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.711 if tag == 'replace':
2025-07-02 06:41:18.712 atags += '^' * la
2025-07-02 06:41:18.712 btags += '^' * lb
2025-07-02 06:41:18.712 elif tag == 'delete':
2025-07-02 06:41:18.712 atags += '-' * la
2025-07-02 06:41:18.712 elif tag == 'insert':
2025-07-02 06:41:18.712 btags += '+' * lb
2025-07-02 06:41:18.712 elif tag == 'equal':
2025-07-02 06:41:18.712 atags += ' ' * la
2025-07-02 06:41:18.712 btags += ' ' * lb
2025-07-02 06:41:18.712 else:
2025-07-02 06:41:18.712 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.712 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.712 else:
2025-07-02 06:41:18.712 # the synch pair is identical
2025-07-02 06:41:18.712 yield ' ' + aelt
2025-07-02 06:41:18.712
2025-07-02 06:41:18.713 # pump out diffs from after the synch point
2025-07-02 06:41:18.713 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.713
2025-07-02 06:41:18.713 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.713 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.713
2025-07-02 06:41:18.713 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.713 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.713 alo = 447, ahi = 1101
2025-07-02 06:41:18.713 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.713 blo = 447, bhi = 1101
2025-07-02 06:41:18.713
2025-07-02 06:41:18.713 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.713 g = []
2025-07-02 06:41:18.713 if alo < ahi:
2025-07-02 06:41:18.713 if blo < bhi:
2025-07-02 06:41:18.714 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.714 else:
2025-07-02 06:41:18.714 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.714 elif blo < bhi:
2025-07-02 06:41:18.714 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.714
2025-07-02 06:41:18.714 > yield from g
2025-07-02 06:41:18.714
2025-07-02 06:41:18.714 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.714 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.714
2025-07-02 06:41:18.714 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.714 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.714 alo = 447, ahi = 1101
2025-07-02 06:41:18.714 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.715 blo = 447, bhi = 1101
2025-07-02 06:41:18.715
2025-07-02 06:41:18.715 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.715 r"""
2025-07-02 06:41:18.715 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.715 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.715 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.715 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.715
2025-07-02 06:41:18.715 Example:
2025-07-02 06:41:18.715
2025-07-02 06:41:18.715 >>> d = Differ()
2025-07-02 06:41:18.715 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.715 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.715 >>> print(''.join(results), end="")
2025-07-02 06:41:18.715 - abcDefghiJkl
2025-07-02 06:41:18.716 + abcdefGhijkl
2025-07-02 06:41:18.716 """
2025-07-02 06:41:18.716
2025-07-02 06:41:18.716 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.716 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.716 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.716 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.716 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.716
2025-07-02 06:41:18.716 # search for the pair that matches best without being identical
2025-07-02 06:41:18.716 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.716 # on junk -- unless we have to)
2025-07-02 06:41:18.716 for j in range(blo, bhi):
2025-07-02 06:41:18.716 bj = b[j]
2025-07-02 06:41:18.717 cruncher.set_seq2(bj)
2025-07-02 06:41:18.717 for i in range(alo, ahi):
2025-07-02 06:41:18.717 ai = a[i]
2025-07-02 06:41:18.717 if ai == bj:
2025-07-02 06:41:18.717 if eqi is None:
2025-07-02 06:41:18.717 eqi, eqj = i, j
2025-07-02 06:41:18.717 continue
2025-07-02 06:41:18.717 cruncher.set_seq1(ai)
2025-07-02 06:41:18.717 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.717 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.717 # compares by a factor of 3.
2025-07-02 06:41:18.717 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.717 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.717 # of the computation is cached by cruncher
2025-07-02 06:41:18.717 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.717 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.718 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.718 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.718 if best_ratio < cutoff:
2025-07-02 06:41:18.718 # no non-identical "pretty close" pair
2025-07-02 06:41:18.718 if eqi is None:
2025-07-02 06:41:18.718 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.718 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.718 return
2025-07-02 06:41:18.718 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.718 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.718 else:
2025-07-02 06:41:18.718 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.718 eqi = None
2025-07-02 06:41:18.718
2025-07-02 06:41:18.718 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.718 # identical
2025-07-02 06:41:18.719
2025-07-02 06:41:18.719 # pump out diffs from before the synch point
2025-07-02 06:41:18.719 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.719
2025-07-02 06:41:18.719 # do intraline marking on the synch pair
2025-07-02 06:41:18.719 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.719 if eqi is None:
2025-07-02 06:41:18.719 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.719 atags = btags = ""
2025-07-02 06:41:18.719 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.719 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.719 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.719 if tag == 'replace':
2025-07-02 06:41:18.719 atags += '^' * la
2025-07-02 06:41:18.719 btags += '^' * lb
2025-07-02 06:41:18.719 elif tag == 'delete':
2025-07-02 06:41:18.720 atags += '-' * la
2025-07-02 06:41:18.720 elif tag == 'insert':
2025-07-02 06:41:18.720 btags += '+' * lb
2025-07-02 06:41:18.720 elif tag == 'equal':
2025-07-02 06:41:18.720 atags += ' ' * la
2025-07-02 06:41:18.720 btags += ' ' * lb
2025-07-02 06:41:18.720 else:
2025-07-02 06:41:18.720 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.720 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.720 else:
2025-07-02 06:41:18.720 # the synch pair is identical
2025-07-02 06:41:18.720 yield ' ' + aelt
2025-07-02 06:41:18.720
2025-07-02 06:41:18.720 # pump out diffs from after the synch point
2025-07-02 06:41:18.720 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.721
2025-07-02 06:41:18.721 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.721 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.721
2025-07-02 06:41:18.721 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.721 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.721 alo = 448, ahi = 1101
2025-07-02 06:41:18.721 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.721 blo = 448, bhi = 1101
2025-07-02 06:41:18.721
2025-07-02 06:41:18.721 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.721 g = []
2025-07-02 06:41:18.721 if alo < ahi:
2025-07-02 06:41:18.721 if blo < bhi:
2025-07-02 06:41:18.722 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.722 else:
2025-07-02 06:41:18.722 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.722 elif blo < bhi:
2025-07-02 06:41:18.722 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.722
2025-07-02 06:41:18.722 > yield from g
2025-07-02 06:41:18.722
2025-07-02 06:41:18.722 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.722 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.722
2025-07-02 06:41:18.722 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.722 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.722 alo = 448, ahi = 1101
2025-07-02 06:41:18.722 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.722 blo = 448, bhi = 1101
2025-07-02 06:41:18.723
2025-07-02 06:41:18.723 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.723 r"""
2025-07-02 06:41:18.723 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.723 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.723 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.723 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.723
2025-07-02 06:41:18.723 Example:
2025-07-02 06:41:18.723
2025-07-02 06:41:18.723 >>> d = Differ()
2025-07-02 06:41:18.723 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.723 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.723 >>> print(''.join(results), end="")
2025-07-02 06:41:18.723 - abcDefghiJkl
2025-07-02 06:41:18.724 + abcdefGhijkl
2025-07-02 06:41:18.724 """
2025-07-02 06:41:18.724
2025-07-02 06:41:18.724 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.724 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.724 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.724 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.724 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.724
2025-07-02 06:41:18.724 # search for the pair that matches best without being identical
2025-07-02 06:41:18.724 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.724 # on junk -- unless we have to)
2025-07-02 06:41:18.724 for j in range(blo, bhi):
2025-07-02 06:41:18.724 bj = b[j]
2025-07-02 06:41:18.724 cruncher.set_seq2(bj)
2025-07-02 06:41:18.725 for i in range(alo, ahi):
2025-07-02 06:41:18.725 ai = a[i]
2025-07-02 06:41:18.725 if ai == bj:
2025-07-02 06:41:18.725 if eqi is None:
2025-07-02 06:41:18.725 eqi, eqj = i, j
2025-07-02 06:41:18.725 continue
2025-07-02 06:41:18.725 cruncher.set_seq1(ai)
2025-07-02 06:41:18.725 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.725 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.725 # compares by a factor of 3.
2025-07-02 06:41:18.725 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.725 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.725 # of the computation is cached by cruncher
2025-07-02 06:41:18.725 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.725 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.725 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.726 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.726 if best_ratio < cutoff:
2025-07-02 06:41:18.726 # no non-identical "pretty close" pair
2025-07-02 06:41:18.726 if eqi is None:
2025-07-02 06:41:18.726 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.726 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.726 return
2025-07-02 06:41:18.726 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.726 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.726 else:
2025-07-02 06:41:18.726 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.726 eqi = None
2025-07-02 06:41:18.726
2025-07-02 06:41:18.726 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.726 # identical
2025-07-02 06:41:18.726
2025-07-02 06:41:18.727 # pump out diffs from before the synch point
2025-07-02 06:41:18.727 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.727
2025-07-02 06:41:18.727 # do intraline marking on the synch pair
2025-07-02 06:41:18.727 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.727 if eqi is None:
2025-07-02 06:41:18.727 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.727 atags = btags = ""
2025-07-02 06:41:18.727 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.727 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.727 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.727 if tag == 'replace':
2025-07-02 06:41:18.727 atags += '^' * la
2025-07-02 06:41:18.727 btags += '^' * lb
2025-07-02 06:41:18.727 elif tag == 'delete':
2025-07-02 06:41:18.727 atags += '-' * la
2025-07-02 06:41:18.727 elif tag == 'insert':
2025-07-02 06:41:18.727 btags += '+' * lb
2025-07-02 06:41:18.728 elif tag == 'equal':
2025-07-02 06:41:18.728 atags += ' ' * la
2025-07-02 06:41:18.728 btags += ' ' * lb
2025-07-02 06:41:18.728 else:
2025-07-02 06:41:18.728 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.728 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.728 else:
2025-07-02 06:41:18.728 # the synch pair is identical
2025-07-02 06:41:18.728 yield ' ' + aelt
2025-07-02 06:41:18.728
2025-07-02 06:41:18.728 # pump out diffs from after the synch point
2025-07-02 06:41:18.728 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.728
2025-07-02 06:41:18.728 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.728 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.728
2025-07-02 06:41:18.728 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.728 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.728 alo = 449, ahi = 1101
2025-07-02 06:41:18.729 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.729 blo = 449, bhi = 1101
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.729 g = []
2025-07-02 06:41:18.729 if alo < ahi:
2025-07-02 06:41:18.729 if blo < bhi:
2025-07-02 06:41:18.729 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.729 else:
2025-07-02 06:41:18.729 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.729 elif blo < bhi:
2025-07-02 06:41:18.729 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 > yield from g
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.729 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.730 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.730 alo = 449, ahi = 1101
2025-07-02 06:41:18.730 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.730 blo = 449, bhi = 1101
2025-07-02 06:41:18.730
2025-07-02 06:41:18.730 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.730 r"""
2025-07-02 06:41:18.730 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.730 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.730 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.730 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.730
2025-07-02 06:41:18.730 Example:
2025-07-02 06:41:18.730
2025-07-02 06:41:18.730 >>> d = Differ()
2025-07-02 06:41:18.730 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.730 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.730 >>> print(''.join(results), end="")
2025-07-02 06:41:18.730 - abcDefghiJkl
2025-07-02 06:41:18.731 + abcdefGhijkl
2025-07-02 06:41:18.731 """
2025-07-02 06:41:18.731
2025-07-02 06:41:18.731 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.731 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.731 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.731 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.731 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.731
2025-07-02 06:41:18.731 # search for the pair that matches best without being identical
2025-07-02 06:41:18.731 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.731 # on junk -- unless we have to)
2025-07-02 06:41:18.731 for j in range(blo, bhi):
2025-07-02 06:41:18.731 bj = b[j]
2025-07-02 06:41:18.731 cruncher.set_seq2(bj)
2025-07-02 06:41:18.731 for i in range(alo, ahi):
2025-07-02 06:41:18.731 ai = a[i]
2025-07-02 06:41:18.732 if ai == bj:
2025-07-02 06:41:18.732 if eqi is None:
2025-07-02 06:41:18.732 eqi, eqj = i, j
2025-07-02 06:41:18.732 continue
2025-07-02 06:41:18.732 cruncher.set_seq1(ai)
2025-07-02 06:41:18.732 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.732 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.732 # compares by a factor of 3.
2025-07-02 06:41:18.732 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.732 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.732 # of the computation is cached by cruncher
2025-07-02 06:41:18.732 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.732 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.732 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.732 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.732 if best_ratio < cutoff:
2025-07-02 06:41:18.732 # no non-identical "pretty close" pair
2025-07-02 06:41:18.732 if eqi is None:
2025-07-02 06:41:18.732 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.733 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.733 return
2025-07-02 06:41:18.733 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.733 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.733 else:
2025-07-02 06:41:18.733 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.733 eqi = None
2025-07-02 06:41:18.733
2025-07-02 06:41:18.733 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.733 # identical
2025-07-02 06:41:18.733
2025-07-02 06:41:18.733 # pump out diffs from before the synch point
2025-07-02 06:41:18.733 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.733
2025-07-02 06:41:18.733 # do intraline marking on the synch pair
2025-07-02 06:41:18.733 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.733 if eqi is None:
2025-07-02 06:41:18.733 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.734 atags = btags = ""
2025-07-02 06:41:18.734 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.734 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.734 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.734 if tag == 'replace':
2025-07-02 06:41:18.734 atags += '^' * la
2025-07-02 06:41:18.734 btags += '^' * lb
2025-07-02 06:41:18.734 elif tag == 'delete':
2025-07-02 06:41:18.734 atags += '-' * la
2025-07-02 06:41:18.734 elif tag == 'insert':
2025-07-02 06:41:18.734 btags += '+' * lb
2025-07-02 06:41:18.734 elif tag == 'equal':
2025-07-02 06:41:18.734 atags += ' ' * la
2025-07-02 06:41:18.734 btags += ' ' * lb
2025-07-02 06:41:18.734 else:
2025-07-02 06:41:18.734 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.734 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.734 else:
2025-07-02 06:41:18.734 # the synch pair is identical
2025-07-02 06:41:18.734 yield ' ' + aelt
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735 # pump out diffs from after the synch point
2025-07-02 06:41:18.735 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.735 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.735 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.735 alo = 450, ahi = 1101
2025-07-02 06:41:18.735 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.735 blo = 450, bhi = 1101
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.735 g = []
2025-07-02 06:41:18.735 if alo < ahi:
2025-07-02 06:41:18.735 if blo < bhi:
2025-07-02 06:41:18.735 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.736 else:
2025-07-02 06:41:18.736 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.736 elif blo < bhi:
2025-07-02 06:41:18.736 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.736
2025-07-02 06:41:18.736 > yield from g
2025-07-02 06:41:18.736
2025-07-02 06:41:18.736 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.736 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.736
2025-07-02 06:41:18.736 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.736 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.736 alo = 450, ahi = 1101
2025-07-02 06:41:18.736 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.736 blo = 450, bhi = 1101
2025-07-02 06:41:18.737
2025-07-02 06:41:18.737 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.737 r"""
2025-07-02 06:41:18.737 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.737 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.737 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.737 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.737
2025-07-02 06:41:18.737 Example:
2025-07-02 06:41:18.737
2025-07-02 06:41:18.737 >>> d = Differ()
2025-07-02 06:41:18.737 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.737 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.737 >>> print(''.join(results), end="")
2025-07-02 06:41:18.737 - abcDefghiJkl
2025-07-02 06:41:18.737 + abcdefGhijkl
2025-07-02 06:41:18.738 """
2025-07-02 06:41:18.738
2025-07-02 06:41:18.738 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.738 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.738 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.738 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.738 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.738
2025-07-02 06:41:18.738 # search for the pair that matches best without being identical
2025-07-02 06:41:18.738 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.738 # on junk -- unless we have to)
2025-07-02 06:41:18.738 for j in range(blo, bhi):
2025-07-02 06:41:18.738 bj = b[j]
2025-07-02 06:41:18.738 cruncher.set_seq2(bj)
2025-07-02 06:41:18.738 for i in range(alo, ahi):
2025-07-02 06:41:18.738 ai = a[i]
2025-07-02 06:41:18.738 if ai == bj:
2025-07-02 06:41:18.738 if eqi is None:
2025-07-02 06:41:18.738 eqi, eqj = i, j
2025-07-02 06:41:18.739 continue
2025-07-02 06:41:18.739 cruncher.set_seq1(ai)
2025-07-02 06:41:18.739 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.739 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.739 # compares by a factor of 3.
2025-07-02 06:41:18.739 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.739 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.739 # of the computation is cached by cruncher
2025-07-02 06:41:18.739 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.739 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.739 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.739 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.739 if best_ratio < cutoff:
2025-07-02 06:41:18.739 # no non-identical "pretty close" pair
2025-07-02 06:41:18.739 if eqi is None:
2025-07-02 06:41:18.739 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.739 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.739 return
2025-07-02 06:41:18.739 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.740 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.740 else:
2025-07-02 06:41:18.740 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.740 eqi = None
2025-07-02 06:41:18.740
2025-07-02 06:41:18.740 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.740 # identical
2025-07-02 06:41:18.740
2025-07-02 06:41:18.740 # pump out diffs from before the synch point
2025-07-02 06:41:18.740 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.740
2025-07-02 06:41:18.740 # do intraline marking on the synch pair
2025-07-02 06:41:18.740 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.740 if eqi is None:
2025-07-02 06:41:18.740 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.740 atags = btags = ""
2025-07-02 06:41:18.740 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.740 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.740 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.741 if tag == 'replace':
2025-07-02 06:41:18.741 atags += '^' * la
2025-07-02 06:41:18.741 btags += '^' * lb
2025-07-02 06:41:18.741 elif tag == 'delete':
2025-07-02 06:41:18.741 atags += '-' * la
2025-07-02 06:41:18.741 elif tag == 'insert':
2025-07-02 06:41:18.741 btags += '+' * lb
2025-07-02 06:41:18.741 elif tag == 'equal':
2025-07-02 06:41:18.741 atags += ' ' * la
2025-07-02 06:41:18.741 btags += ' ' * lb
2025-07-02 06:41:18.741 else:
2025-07-02 06:41:18.741 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.741 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.741 else:
2025-07-02 06:41:18.741 # the synch pair is identical
2025-07-02 06:41:18.741 yield ' ' + aelt
2025-07-02 06:41:18.741
2025-07-02 06:41:18.741 # pump out diffs from after the synch point
2025-07-02 06:41:18.741 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.741
2025-07-02 06:41:18.742 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.742 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.742
2025-07-02 06:41:18.742 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.742 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.742 alo = 451, ahi = 1101
2025-07-02 06:41:18.742 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.742 blo = 451, bhi = 1101
2025-07-02 06:41:18.742
2025-07-02 06:41:18.742 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.742 g = []
2025-07-02 06:41:18.742 if alo < ahi:
2025-07-02 06:41:18.742 if blo < bhi:
2025-07-02 06:41:18.742 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.742 else:
2025-07-02 06:41:18.742 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.742 elif blo < bhi:
2025-07-02 06:41:18.743 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 > yield from g
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.743 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.743 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.743 alo = 451, ahi = 1101
2025-07-02 06:41:18.743 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.743 blo = 451, bhi = 1101
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.743 r"""
2025-07-02 06:41:18.743 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.743 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.743 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.743 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.744
2025-07-02 06:41:18.744 Example:
2025-07-02 06:41:18.744
2025-07-02 06:41:18.744 >>> d = Differ()
2025-07-02 06:41:18.744 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.744 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.744 >>> print(''.join(results), end="")
2025-07-02 06:41:18.744 - abcDefghiJkl
2025-07-02 06:41:18.744 + abcdefGhijkl
2025-07-02 06:41:18.744 """
2025-07-02 06:41:18.744
2025-07-02 06:41:18.744 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.744 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.744 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.744 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.744 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.744
2025-07-02 06:41:18.745 # search for the pair that matches best without being identical
2025-07-02 06:41:18.745 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.745 # on junk -- unless we have to)
2025-07-02 06:41:18.745 for j in range(blo, bhi):
2025-07-02 06:41:18.745 bj = b[j]
2025-07-02 06:41:18.745 cruncher.set_seq2(bj)
2025-07-02 06:41:18.745 for i in range(alo, ahi):
2025-07-02 06:41:18.745 ai = a[i]
2025-07-02 06:41:18.745 if ai == bj:
2025-07-02 06:41:18.745 if eqi is None:
2025-07-02 06:41:18.745 eqi, eqj = i, j
2025-07-02 06:41:18.745 continue
2025-07-02 06:41:18.745 cruncher.set_seq1(ai)
2025-07-02 06:41:18.745 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.745 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.745 # compares by a factor of 3.
2025-07-02 06:41:18.745 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.745 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.745 # of the computation is cached by cruncher
2025-07-02 06:41:18.745 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.746 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.746 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.746 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.746 if best_ratio < cutoff:
2025-07-02 06:41:18.746 # no non-identical "pretty close" pair
2025-07-02 06:41:18.746 if eqi is None:
2025-07-02 06:41:18.746 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.746 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.746 return
2025-07-02 06:41:18.746 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.746 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.746 else:
2025-07-02 06:41:18.746 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.746 eqi = None
2025-07-02 06:41:18.746
2025-07-02 06:41:18.746 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.746 # identical
2025-07-02 06:41:18.746
2025-07-02 06:41:18.746 # pump out diffs from before the synch point
2025-07-02 06:41:18.747 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.747
2025-07-02 06:41:18.747 # do intraline marking on the synch pair
2025-07-02 06:41:18.747 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.747 if eqi is None:
2025-07-02 06:41:18.747 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.747 atags = btags = ""
2025-07-02 06:41:18.747 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.747 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.747 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.747 if tag == 'replace':
2025-07-02 06:41:18.747 atags += '^' * la
2025-07-02 06:41:18.747 btags += '^' * lb
2025-07-02 06:41:18.747 elif tag == 'delete':
2025-07-02 06:41:18.747 atags += '-' * la
2025-07-02 06:41:18.747 elif tag == 'insert':
2025-07-02 06:41:18.747 btags += '+' * lb
2025-07-02 06:41:18.747 elif tag == 'equal':
2025-07-02 06:41:18.747 atags += ' ' * la
2025-07-02 06:41:18.747 btags += ' ' * lb
2025-07-02 06:41:18.748 else:
2025-07-02 06:41:18.748 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.748 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.748 else:
2025-07-02 06:41:18.748 # the synch pair is identical
2025-07-02 06:41:18.748 yield ' ' + aelt
2025-07-02 06:41:18.748
2025-07-02 06:41:18.748 # pump out diffs from after the synch point
2025-07-02 06:41:18.748 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.748
2025-07-02 06:41:18.748 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.748 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.748
2025-07-02 06:41:18.748 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.748 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.748 alo = 452, ahi = 1101
2025-07-02 06:41:18.748 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.748 blo = 452, bhi = 1101
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.749 g = []
2025-07-02 06:41:18.749 if alo < ahi:
2025-07-02 06:41:18.749 if blo < bhi:
2025-07-02 06:41:18.749 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.749 else:
2025-07-02 06:41:18.749 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.749 elif blo < bhi:
2025-07-02 06:41:18.749 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 > yield from g
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.749 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.749 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.749 alo = 452, ahi = 1101
2025-07-02 06:41:18.749 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.750 blo = 452, bhi = 1101
2025-07-02 06:41:18.750
2025-07-02 06:41:18.750 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.750 r"""
2025-07-02 06:41:18.750 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.750 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.750 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.750 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.750
2025-07-02 06:41:18.750 Example:
2025-07-02 06:41:18.750
2025-07-02 06:41:18.750 >>> d = Differ()
2025-07-02 06:41:18.750 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.750 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.750 >>> print(''.join(results), end="")
2025-07-02 06:41:18.750 - abcDefghiJkl
2025-07-02 06:41:18.750 + abcdefGhijkl
2025-07-02 06:41:18.751 """
2025-07-02 06:41:18.751
2025-07-02 06:41:18.751 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.751 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.751 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.751 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.751 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.751
2025-07-02 06:41:18.751 # search for the pair that matches best without being identical
2025-07-02 06:41:18.751 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.751 # on junk -- unless we have to)
2025-07-02 06:41:18.751 for j in range(blo, bhi):
2025-07-02 06:41:18.751 bj = b[j]
2025-07-02 06:41:18.751 cruncher.set_seq2(bj)
2025-07-02 06:41:18.751 for i in range(alo, ahi):
2025-07-02 06:41:18.751 ai = a[i]
2025-07-02 06:41:18.751 if ai == bj:
2025-07-02 06:41:18.751 if eqi is None:
2025-07-02 06:41:18.751 eqi, eqj = i, j
2025-07-02 06:41:18.751 continue
2025-07-02 06:41:18.752 cruncher.set_seq1(ai)
2025-07-02 06:41:18.752 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.752 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.752 # compares by a factor of 3.
2025-07-02 06:41:18.752 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.752 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.752 # of the computation is cached by cruncher
2025-07-02 06:41:18.752 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.752 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.752 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.752 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.752 if best_ratio < cutoff:
2025-07-02 06:41:18.752 # no non-identical "pretty close" pair
2025-07-02 06:41:18.752 if eqi is None:
2025-07-02 06:41:18.752 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.752 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.752 return
2025-07-02 06:41:18.752 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.752 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.753 else:
2025-07-02 06:41:18.753 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.753 eqi = None
2025-07-02 06:41:18.753
2025-07-02 06:41:18.753 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.753 # identical
2025-07-02 06:41:18.753
2025-07-02 06:41:18.753 # pump out diffs from before the synch point
2025-07-02 06:41:18.753 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.753
2025-07-02 06:41:18.753 # do intraline marking on the synch pair
2025-07-02 06:41:18.753 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.753 if eqi is None:
2025-07-02 06:41:18.753 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.753 atags = btags = ""
2025-07-02 06:41:18.753 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.753 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.753 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.754 if tag == 'replace':
2025-07-02 06:41:18.754 atags += '^' * la
2025-07-02 06:41:18.754 btags += '^' * lb
2025-07-02 06:41:18.754 elif tag == 'delete':
2025-07-02 06:41:18.754 atags += '-' * la
2025-07-02 06:41:18.754 elif tag == 'insert':
2025-07-02 06:41:18.754 btags += '+' * lb
2025-07-02 06:41:18.754 elif tag == 'equal':
2025-07-02 06:41:18.754 atags += ' ' * la
2025-07-02 06:41:18.754 btags += ' ' * lb
2025-07-02 06:41:18.754 else:
2025-07-02 06:41:18.754 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.754 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.754 else:
2025-07-02 06:41:18.754 # the synch pair is identical
2025-07-02 06:41:18.754 yield ' ' + aelt
2025-07-02 06:41:18.754
2025-07-02 06:41:18.754 # pump out diffs from after the synch point
2025-07-02 06:41:18.754 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.755
2025-07-02 06:41:18.755 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.755 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.755
2025-07-02 06:41:18.755 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.755 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.755 alo = 453, ahi = 1101
2025-07-02 06:41:18.755 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.755 blo = 453, bhi = 1101
2025-07-02 06:41:18.755
2025-07-02 06:41:18.755 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.755 g = []
2025-07-02 06:41:18.755 if alo < ahi:
2025-07-02 06:41:18.755 if blo < bhi:
2025-07-02 06:41:18.755 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.755 else:
2025-07-02 06:41:18.755 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.755 elif blo < bhi:
2025-07-02 06:41:18.755 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 > yield from g
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.756 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.756 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.756 alo = 453, ahi = 1101
2025-07-02 06:41:18.756 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.756 blo = 453, bhi = 1101
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.756 r"""
2025-07-02 06:41:18.756 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.756 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.756 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.756 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.756
2025-07-02 06:41:18.757 Example:
2025-07-02 06:41:18.757
2025-07-02 06:41:18.757 >>> d = Differ()
2025-07-02 06:41:18.757 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.757 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.757 >>> print(''.join(results), end="")
2025-07-02 06:41:18.757 - abcDefghiJkl
2025-07-02 06:41:18.757 + abcdefGhijkl
2025-07-02 06:41:18.757 """
2025-07-02 06:41:18.757
2025-07-02 06:41:18.757 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.757 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.757 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.757 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.757 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.757
2025-07-02 06:41:18.757 # search for the pair that matches best without being identical
2025-07-02 06:41:18.757 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.758 # on junk -- unless we have to)
2025-07-02 06:41:18.758 for j in range(blo, bhi):
2025-07-02 06:41:18.758 bj = b[j]
2025-07-02 06:41:18.758 cruncher.set_seq2(bj)
2025-07-02 06:41:18.758 for i in range(alo, ahi):
2025-07-02 06:41:18.758 ai = a[i]
2025-07-02 06:41:18.758 if ai == bj:
2025-07-02 06:41:18.758 if eqi is None:
2025-07-02 06:41:18.758 eqi, eqj = i, j
2025-07-02 06:41:18.758 continue
2025-07-02 06:41:18.758 cruncher.set_seq1(ai)
2025-07-02 06:41:18.758 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.758 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.758 # compares by a factor of 3.
2025-07-02 06:41:18.758 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.758 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.758 # of the computation is cached by cruncher
2025-07-02 06:41:18.758 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.758 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.759 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.759 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.759 if best_ratio < cutoff:
2025-07-02 06:41:18.759 # no non-identical "pretty close" pair
2025-07-02 06:41:18.759 if eqi is None:
2025-07-02 06:41:18.759 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.759 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.759 return
2025-07-02 06:41:18.759 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.759 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.759 else:
2025-07-02 06:41:18.759 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.759 eqi = None
2025-07-02 06:41:18.759
2025-07-02 06:41:18.759 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.759 # identical
2025-07-02 06:41:18.759
2025-07-02 06:41:18.759 # pump out diffs from before the synch point
2025-07-02 06:41:18.759 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.760
2025-07-02 06:41:18.760 # do intraline marking on the synch pair
2025-07-02 06:41:18.760 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.760 if eqi is None:
2025-07-02 06:41:18.760 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.760 atags = btags = ""
2025-07-02 06:41:18.760 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.760 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.760 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.760 if tag == 'replace':
2025-07-02 06:41:18.760 atags += '^' * la
2025-07-02 06:41:18.760 btags += '^' * lb
2025-07-02 06:41:18.760 elif tag == 'delete':
2025-07-02 06:41:18.760 atags += '-' * la
2025-07-02 06:41:18.760 elif tag == 'insert':
2025-07-02 06:41:18.760 btags += '+' * lb
2025-07-02 06:41:18.760 elif tag == 'equal':
2025-07-02 06:41:18.760 atags += ' ' * la
2025-07-02 06:41:18.761 btags += ' ' * lb
2025-07-02 06:41:18.761 else:
2025-07-02 06:41:18.761 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.761 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.761 else:
2025-07-02 06:41:18.761 # the synch pair is identical
2025-07-02 06:41:18.761 yield ' ' + aelt
2025-07-02 06:41:18.761
2025-07-02 06:41:18.761 # pump out diffs from after the synch point
2025-07-02 06:41:18.761 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.761
2025-07-02 06:41:18.761 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.761 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.761
2025-07-02 06:41:18.761 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.761 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.761 alo = 454, ahi = 1101
2025-07-02 06:41:18.761 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.761 blo = 454, bhi = 1101
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.762 g = []
2025-07-02 06:41:18.762 if alo < ahi:
2025-07-02 06:41:18.762 if blo < bhi:
2025-07-02 06:41:18.762 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.762 else:
2025-07-02 06:41:18.762 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.762 elif blo < bhi:
2025-07-02 06:41:18.762 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 > yield from g
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.762 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.762 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.762 alo = 454, ahi = 1101
2025-07-02 06:41:18.763 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.763 blo = 454, bhi = 1101
2025-07-02 06:41:18.763
2025-07-02 06:41:18.763 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.763 r"""
2025-07-02 06:41:18.763 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.763 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.763 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.763 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.763
2025-07-02 06:41:18.763 Example:
2025-07-02 06:41:18.763
2025-07-02 06:41:18.763 >>> d = Differ()
2025-07-02 06:41:18.763 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.763 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.763 >>> print(''.join(results), end="")
2025-07-02 06:41:18.763 - abcDefghiJkl
2025-07-02 06:41:18.763 + abcdefGhijkl
2025-07-02 06:41:18.764 """
2025-07-02 06:41:18.764
2025-07-02 06:41:18.764 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.764 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.764 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.764 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.764 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.764
2025-07-02 06:41:18.764 # search for the pair that matches best without being identical
2025-07-02 06:41:18.764 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.764 # on junk -- unless we have to)
2025-07-02 06:41:18.764 for j in range(blo, bhi):
2025-07-02 06:41:18.764 bj = b[j]
2025-07-02 06:41:18.764 cruncher.set_seq2(bj)
2025-07-02 06:41:18.764 for i in range(alo, ahi):
2025-07-02 06:41:18.764 ai = a[i]
2025-07-02 06:41:18.764 if ai == bj:
2025-07-02 06:41:18.764 if eqi is None:
2025-07-02 06:41:18.764 eqi, eqj = i, j
2025-07-02 06:41:18.765 continue
2025-07-02 06:41:18.765 cruncher.set_seq1(ai)
2025-07-02 06:41:18.765 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.765 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.765 # compares by a factor of 3.
2025-07-02 06:41:18.765 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.765 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.765 # of the computation is cached by cruncher
2025-07-02 06:41:18.765 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.765 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.765 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.765 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.765 if best_ratio < cutoff:
2025-07-02 06:41:18.765 # no non-identical "pretty close" pair
2025-07-02 06:41:18.765 if eqi is None:
2025-07-02 06:41:18.765 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.765 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.765 return
2025-07-02 06:41:18.765 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.766 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.766 else:
2025-07-02 06:41:18.766 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.766 eqi = None
2025-07-02 06:41:18.766
2025-07-02 06:41:18.766 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.766 # identical
2025-07-02 06:41:18.766
2025-07-02 06:41:18.766 # pump out diffs from before the synch point
2025-07-02 06:41:18.766 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.766
2025-07-02 06:41:18.766 # do intraline marking on the synch pair
2025-07-02 06:41:18.766 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.766 if eqi is None:
2025-07-02 06:41:18.766 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.766 atags = btags = ""
2025-07-02 06:41:18.766 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.766 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.766 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.767 if tag == 'replace':
2025-07-02 06:41:18.767 atags += '^' * la
2025-07-02 06:41:18.767 btags += '^' * lb
2025-07-02 06:41:18.767 elif tag == 'delete':
2025-07-02 06:41:18.767 atags += '-' * la
2025-07-02 06:41:18.767 elif tag == 'insert':
2025-07-02 06:41:18.767 btags += '+' * lb
2025-07-02 06:41:18.767 elif tag == 'equal':
2025-07-02 06:41:18.767 atags += ' ' * la
2025-07-02 06:41:18.767 btags += ' ' * lb
2025-07-02 06:41:18.767 else:
2025-07-02 06:41:18.767 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.767 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.767 else:
2025-07-02 06:41:18.767 # the synch pair is identical
2025-07-02 06:41:18.767 yield ' ' + aelt
2025-07-02 06:41:18.767
2025-07-02 06:41:18.767 # pump out diffs from after the synch point
2025-07-02 06:41:18.767 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.767
2025-07-02 06:41:18.768 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.768 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.768
2025-07-02 06:41:18.768 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.768 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.768 alo = 455, ahi = 1101
2025-07-02 06:41:18.768 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.768 blo = 455, bhi = 1101
2025-07-02 06:41:18.768
2025-07-02 06:41:18.768 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.768 g = []
2025-07-02 06:41:18.768 if alo < ahi:
2025-07-02 06:41:18.768 if blo < bhi:
2025-07-02 06:41:18.768 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.768 else:
2025-07-02 06:41:18.768 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.768 elif blo < bhi:
2025-07-02 06:41:18.768 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.768
2025-07-02 06:41:18.769 > yield from g
2025-07-02 06:41:18.769
2025-07-02 06:41:18.769 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.769 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.769
2025-07-02 06:41:18.769 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.769 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.769 alo = 455, ahi = 1101
2025-07-02 06:41:18.769 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.769 blo = 455, bhi = 1101
2025-07-02 06:41:18.769
2025-07-02 06:41:18.769 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.769 r"""
2025-07-02 06:41:18.769 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.769 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.769 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.769 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.769
2025-07-02 06:41:18.770 Example:
2025-07-02 06:41:18.770
2025-07-02 06:41:18.770 >>> d = Differ()
2025-07-02 06:41:18.770 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.770 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.770 >>> print(''.join(results), end="")
2025-07-02 06:41:18.770 - abcDefghiJkl
2025-07-02 06:41:18.770 + abcdefGhijkl
2025-07-02 06:41:18.770 """
2025-07-02 06:41:18.770
2025-07-02 06:41:18.770 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.770 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.770 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.770 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.770 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.770
2025-07-02 06:41:18.770 # search for the pair that matches best without being identical
2025-07-02 06:41:18.771 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.771 # on junk -- unless we have to)
2025-07-02 06:41:18.771 for j in range(blo, bhi):
2025-07-02 06:41:18.771 bj = b[j]
2025-07-02 06:41:18.771 cruncher.set_seq2(bj)
2025-07-02 06:41:18.771 for i in range(alo, ahi):
2025-07-02 06:41:18.771 ai = a[i]
2025-07-02 06:41:18.771 if ai == bj:
2025-07-02 06:41:18.771 if eqi is None:
2025-07-02 06:41:18.771 eqi, eqj = i, j
2025-07-02 06:41:18.771 continue
2025-07-02 06:41:18.771 cruncher.set_seq1(ai)
2025-07-02 06:41:18.771 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.771 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.771 # compares by a factor of 3.
2025-07-02 06:41:18.771 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.771 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.771 # of the computation is cached by cruncher
2025-07-02 06:41:18.771 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.771 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.772 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.772 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.772 if best_ratio < cutoff:
2025-07-02 06:41:18.772 # no non-identical "pretty close" pair
2025-07-02 06:41:18.772 if eqi is None:
2025-07-02 06:41:18.772 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.772 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.772 return
2025-07-02 06:41:18.772 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.772 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.772 else:
2025-07-02 06:41:18.772 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.772 eqi = None
2025-07-02 06:41:18.772
2025-07-02 06:41:18.772 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.772 # identical
2025-07-02 06:41:18.772
2025-07-02 06:41:18.772 # pump out diffs from before the synch point
2025-07-02 06:41:18.772 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.773
2025-07-02 06:41:18.773 # do intraline marking on the synch pair
2025-07-02 06:41:18.773 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.773 if eqi is None:
2025-07-02 06:41:18.773 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.773 atags = btags = ""
2025-07-02 06:41:18.773 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.773 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.773 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.773 if tag == 'replace':
2025-07-02 06:41:18.773 atags += '^' * la
2025-07-02 06:41:18.773 btags += '^' * lb
2025-07-02 06:41:18.773 elif tag == 'delete':
2025-07-02 06:41:18.773 atags += '-' * la
2025-07-02 06:41:18.773 elif tag == 'insert':
2025-07-02 06:41:18.773 btags += '+' * lb
2025-07-02 06:41:18.773 elif tag == 'equal':
2025-07-02 06:41:18.773 atags += ' ' * la
2025-07-02 06:41:18.773 btags += ' ' * lb
2025-07-02 06:41:18.773 else:
2025-07-02 06:41:18.774 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.774 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.774 else:
2025-07-02 06:41:18.774 # the synch pair is identical
2025-07-02 06:41:18.774 yield ' ' + aelt
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774 # pump out diffs from after the synch point
2025-07-02 06:41:18.774 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.774 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.774 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.774 alo = 456, ahi = 1101
2025-07-02 06:41:18.774 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.774 blo = 456, bhi = 1101
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.775 g = []
2025-07-02 06:41:18.775 if alo < ahi:
2025-07-02 06:41:18.775 if blo < bhi:
2025-07-02 06:41:18.775 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.775 else:
2025-07-02 06:41:18.775 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.775 elif blo < bhi:
2025-07-02 06:41:18.775 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.775
2025-07-02 06:41:18.775 > yield from g
2025-07-02 06:41:18.775
2025-07-02 06:41:18.775 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.775 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.775
2025-07-02 06:41:18.775 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.775 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.775 alo = 456, ahi = 1101
2025-07-02 06:41:18.775 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.775 blo = 456, bhi = 1101
2025-07-02 06:41:18.776
2025-07-02 06:41:18.776 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.776 r"""
2025-07-02 06:41:18.776 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.776 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.776 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.776 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.776
2025-07-02 06:41:18.776 Example:
2025-07-02 06:41:18.776
2025-07-02 06:41:18.776 >>> d = Differ()
2025-07-02 06:41:18.776 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.776 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.776 >>> print(''.join(results), end="")
2025-07-02 06:41:18.776 - abcDefghiJkl
2025-07-02 06:41:18.776 + abcdefGhijkl
2025-07-02 06:41:18.776 """
2025-07-02 06:41:18.776
2025-07-02 06:41:18.777 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.777 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.777 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.777 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.777 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.777
2025-07-02 06:41:18.777 # search for the pair that matches best without being identical
2025-07-02 06:41:18.777 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.777 # on junk -- unless we have to)
2025-07-02 06:41:18.777 for j in range(blo, bhi):
2025-07-02 06:41:18.777 bj = b[j]
2025-07-02 06:41:18.777 cruncher.set_seq2(bj)
2025-07-02 06:41:18.777 for i in range(alo, ahi):
2025-07-02 06:41:18.777 ai = a[i]
2025-07-02 06:41:18.777 if ai == bj:
2025-07-02 06:41:18.777 if eqi is None:
2025-07-02 06:41:18.777 eqi, eqj = i, j
2025-07-02 06:41:18.777 continue
2025-07-02 06:41:18.778 cruncher.set_seq1(ai)
2025-07-02 06:41:18.778 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.778 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.778 # compares by a factor of 3.
2025-07-02 06:41:18.778 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.778 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.778 # of the computation is cached by cruncher
2025-07-02 06:41:18.778 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.778 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.778 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.778 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.778 if best_ratio < cutoff:
2025-07-02 06:41:18.778 # no non-identical "pretty close" pair
2025-07-02 06:41:18.778 if eqi is None:
2025-07-02 06:41:18.778 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.778 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.778 return
2025-07-02 06:41:18.778 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.778 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.779 else:
2025-07-02 06:41:18.779 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.779 eqi = None
2025-07-02 06:41:18.779
2025-07-02 06:41:18.779 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.779 # identical
2025-07-02 06:41:18.779
2025-07-02 06:41:18.779 # pump out diffs from before the synch point
2025-07-02 06:41:18.779 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.779
2025-07-02 06:41:18.779 # do intraline marking on the synch pair
2025-07-02 06:41:18.779 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.779 if eqi is None:
2025-07-02 06:41:18.779 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.779 atags = btags = ""
2025-07-02 06:41:18.779 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.779 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.779 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.779 if tag == 'replace':
2025-07-02 06:41:18.779 atags += '^' * la
2025-07-02 06:41:18.780 btags += '^' * lb
2025-07-02 06:41:18.780 elif tag == 'delete':
2025-07-02 06:41:18.780 atags += '-' * la
2025-07-02 06:41:18.780 elif tag == 'insert':
2025-07-02 06:41:18.780 btags += '+' * lb
2025-07-02 06:41:18.780 elif tag == 'equal':
2025-07-02 06:41:18.780 atags += ' ' * la
2025-07-02 06:41:18.780 btags += ' ' * lb
2025-07-02 06:41:18.780 else:
2025-07-02 06:41:18.780 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.780 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.780 else:
2025-07-02 06:41:18.780 # the synch pair is identical
2025-07-02 06:41:18.780 yield ' ' + aelt
2025-07-02 06:41:18.780
2025-07-02 06:41:18.780 # pump out diffs from after the synch point
2025-07-02 06:41:18.780 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.780
2025-07-02 06:41:18.780 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.781 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.781
2025-07-02 06:41:18.781 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.781 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.781 alo = 457, ahi = 1101
2025-07-02 06:41:18.781 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.781 blo = 457, bhi = 1101
2025-07-02 06:41:18.781
2025-07-02 06:41:18.781 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.781 g = []
2025-07-02 06:41:18.781 if alo < ahi:
2025-07-02 06:41:18.781 if blo < bhi:
2025-07-02 06:41:18.781 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.781 else:
2025-07-02 06:41:18.781 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.781 elif blo < bhi:
2025-07-02 06:41:18.781 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.781
2025-07-02 06:41:18.781 > yield from g
2025-07-02 06:41:18.781
2025-07-02 06:41:18.782 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.782 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.782 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.782 alo = 457, ahi = 1101
2025-07-02 06:41:18.782 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.782 blo = 457, bhi = 1101
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.782 r"""
2025-07-02 06:41:18.782 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.782 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.782 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.782 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782 Example:
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782 >>> d = Differ()
2025-07-02 06:41:18.783 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.783 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.783 >>> print(''.join(results), end="")
2025-07-02 06:41:18.783 - abcDefghiJkl
2025-07-02 06:41:18.783 + abcdefGhijkl
2025-07-02 06:41:18.783 """
2025-07-02 06:41:18.783
2025-07-02 06:41:18.783 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.783 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.783 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.783 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.783 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.783
2025-07-02 06:41:18.783 # search for the pair that matches best without being identical
2025-07-02 06:41:18.783 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.783 # on junk -- unless we have to)
2025-07-02 06:41:18.783 for j in range(blo, bhi):
2025-07-02 06:41:18.784 bj = b[j]
2025-07-02 06:41:18.784 cruncher.set_seq2(bj)
2025-07-02 06:41:18.784 for i in range(alo, ahi):
2025-07-02 06:41:18.784 ai = a[i]
2025-07-02 06:41:18.784 if ai == bj:
2025-07-02 06:41:18.784 if eqi is None:
2025-07-02 06:41:18.784 eqi, eqj = i, j
2025-07-02 06:41:18.784 continue
2025-07-02 06:41:18.784 cruncher.set_seq1(ai)
2025-07-02 06:41:18.784 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.784 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.784 # compares by a factor of 3.
2025-07-02 06:41:18.784 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.784 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.784 # of the computation is cached by cruncher
2025-07-02 06:41:18.784 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.784 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.784 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.784 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.785 if best_ratio < cutoff:
2025-07-02 06:41:18.785 # no non-identical "pretty close" pair
2025-07-02 06:41:18.785 if eqi is None:
2025-07-02 06:41:18.785 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.785 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.785 return
2025-07-02 06:41:18.785 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.785 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.785 else:
2025-07-02 06:41:18.785 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.785 eqi = None
2025-07-02 06:41:18.785
2025-07-02 06:41:18.785 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.785 # identical
2025-07-02 06:41:18.785
2025-07-02 06:41:18.785 # pump out diffs from before the synch point
2025-07-02 06:41:18.785 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.785
2025-07-02 06:41:18.785 # do intraline marking on the synch pair
2025-07-02 06:41:18.786 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.786 if eqi is None:
2025-07-02 06:41:18.786 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.786 atags = btags = ""
2025-07-02 06:41:18.786 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.786 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.786 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.786 if tag == 'replace':
2025-07-02 06:41:18.786 atags += '^' * la
2025-07-02 06:41:18.786 btags += '^' * lb
2025-07-02 06:41:18.786 elif tag == 'delete':
2025-07-02 06:41:18.786 atags += '-' * la
2025-07-02 06:41:18.786 elif tag == 'insert':
2025-07-02 06:41:18.786 btags += '+' * lb
2025-07-02 06:41:18.786 elif tag == 'equal':
2025-07-02 06:41:18.786 atags += ' ' * la
2025-07-02 06:41:18.786 btags += ' ' * lb
2025-07-02 06:41:18.786 else:
2025-07-02 06:41:18.786 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.786 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.787 else:
2025-07-02 06:41:18.787 # the synch pair is identical
2025-07-02 06:41:18.787 yield ' ' + aelt
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787 # pump out diffs from after the synch point
2025-07-02 06:41:18.787 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.787 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.787 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.787 alo = 458, ahi = 1101
2025-07-02 06:41:18.787 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.787 blo = 458, bhi = 1101
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.787 g = []
2025-07-02 06:41:18.788 if alo < ahi:
2025-07-02 06:41:18.788 if blo < bhi:
2025-07-02 06:41:18.788 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.788 else:
2025-07-02 06:41:18.788 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.788 elif blo < bhi:
2025-07-02 06:41:18.788 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.788
2025-07-02 06:41:18.788 > yield from g
2025-07-02 06:41:18.788
2025-07-02 06:41:18.788 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.788 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.788
2025-07-02 06:41:18.788 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.788 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.788 alo = 458, ahi = 1101
2025-07-02 06:41:18.788 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.788 blo = 458, bhi = 1101
2025-07-02 06:41:18.789
2025-07-02 06:41:18.789 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.789 r"""
2025-07-02 06:41:18.789 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.789 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.789 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.789 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.789
2025-07-02 06:41:18.789 Example:
2025-07-02 06:41:18.789
2025-07-02 06:41:18.789 >>> d = Differ()
2025-07-02 06:41:18.789 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.789 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.789 >>> print(''.join(results), end="")
2025-07-02 06:41:18.789 - abcDefghiJkl
2025-07-02 06:41:18.789 + abcdefGhijkl
2025-07-02 06:41:18.789 """
2025-07-02 06:41:18.789
2025-07-02 06:41:18.790 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.790 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.790 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.790 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.790 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.790
2025-07-02 06:41:18.790 # search for the pair that matches best without being identical
2025-07-02 06:41:18.790 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.790 # on junk -- unless we have to)
2025-07-02 06:41:18.790 for j in range(blo, bhi):
2025-07-02 06:41:18.790 bj = b[j]
2025-07-02 06:41:18.790 cruncher.set_seq2(bj)
2025-07-02 06:41:18.790 for i in range(alo, ahi):
2025-07-02 06:41:18.790 ai = a[i]
2025-07-02 06:41:18.790 if ai == bj:
2025-07-02 06:41:18.790 if eqi is None:
2025-07-02 06:41:18.790 eqi, eqj = i, j
2025-07-02 06:41:18.790 continue
2025-07-02 06:41:18.790 cruncher.set_seq1(ai)
2025-07-02 06:41:18.791 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.791 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.791 # compares by a factor of 3.
2025-07-02 06:41:18.791 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.791 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.791 # of the computation is cached by cruncher
2025-07-02 06:41:18.791 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.791 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.791 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.791 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.791 if best_ratio < cutoff:
2025-07-02 06:41:18.791 # no non-identical "pretty close" pair
2025-07-02 06:41:18.791 if eqi is None:
2025-07-02 06:41:18.791 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.791 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.791 return
2025-07-02 06:41:18.791 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.791 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.791 else:
2025-07-02 06:41:18.791 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.792 eqi = None
2025-07-02 06:41:18.792
2025-07-02 06:41:18.792 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.792 # identical
2025-07-02 06:41:18.792
2025-07-02 06:41:18.792 # pump out diffs from before the synch point
2025-07-02 06:41:18.792 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.792
2025-07-02 06:41:18.792 # do intraline marking on the synch pair
2025-07-02 06:41:18.792 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.792 if eqi is None:
2025-07-02 06:41:18.792 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.792 atags = btags = ""
2025-07-02 06:41:18.792 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.792 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.792 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.792 if tag == 'replace':
2025-07-02 06:41:18.792 atags += '^' * la
2025-07-02 06:41:18.792 btags += '^' * lb
2025-07-02 06:41:18.793 elif tag == 'delete':
2025-07-02 06:41:18.793 atags += '-' * la
2025-07-02 06:41:18.793 elif tag == 'insert':
2025-07-02 06:41:18.793 btags += '+' * lb
2025-07-02 06:41:18.793 elif tag == 'equal':
2025-07-02 06:41:18.793 atags += ' ' * la
2025-07-02 06:41:18.793 btags += ' ' * lb
2025-07-02 06:41:18.793 else:
2025-07-02 06:41:18.793 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.793 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.793 else:
2025-07-02 06:41:18.793 # the synch pair is identical
2025-07-02 06:41:18.793 yield ' ' + aelt
2025-07-02 06:41:18.793
2025-07-02 06:41:18.793 # pump out diffs from after the synch point
2025-07-02 06:41:18.793 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.793
2025-07-02 06:41:18.793 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.793 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.793
2025-07-02 06:41:18.794 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.794 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.794 alo = 459, ahi = 1101
2025-07-02 06:41:18.794 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.794 blo = 459, bhi = 1101
2025-07-02 06:41:18.794
2025-07-02 06:41:18.794 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.794 g = []
2025-07-02 06:41:18.794 if alo < ahi:
2025-07-02 06:41:18.794 if blo < bhi:
2025-07-02 06:41:18.794 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.794 else:
2025-07-02 06:41:18.794 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.794 elif blo < bhi:
2025-07-02 06:41:18.794 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.794
2025-07-02 06:41:18.794 > yield from g
2025-07-02 06:41:18.794
2025-07-02 06:41:18.794 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.795 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.795 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.795 alo = 459, ahi = 1101
2025-07-02 06:41:18.795 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.795 blo = 459, bhi = 1101
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.795 r"""
2025-07-02 06:41:18.795 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.795 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.795 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.795 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795 Example:
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795 >>> d = Differ()
2025-07-02 06:41:18.795 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.796 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.796 >>> print(''.join(results), end="")
2025-07-02 06:41:18.796 - abcDefghiJkl
2025-07-02 06:41:18.796 + abcdefGhijkl
2025-07-02 06:41:18.796 """
2025-07-02 06:41:18.796
2025-07-02 06:41:18.796 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.796 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.796 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.796 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.796 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.796
2025-07-02 06:41:18.796 # search for the pair that matches best without being identical
2025-07-02 06:41:18.796 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.796 # on junk -- unless we have to)
2025-07-02 06:41:18.796 for j in range(blo, bhi):
2025-07-02 06:41:18.796 bj = b[j]
2025-07-02 06:41:18.797 cruncher.set_seq2(bj)
2025-07-02 06:41:18.797 for i in range(alo, ahi):
2025-07-02 06:41:18.797 ai = a[i]
2025-07-02 06:41:18.797 if ai == bj:
2025-07-02 06:41:18.797 if eqi is None:
2025-07-02 06:41:18.797 eqi, eqj = i, j
2025-07-02 06:41:18.797 continue
2025-07-02 06:41:18.797 cruncher.set_seq1(ai)
2025-07-02 06:41:18.797 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.797 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.797 # compares by a factor of 3.
2025-07-02 06:41:18.797 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.797 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.797 # of the computation is cached by cruncher
2025-07-02 06:41:18.797 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.797 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.797 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.797 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.797 if best_ratio < cutoff:
2025-07-02 06:41:18.797 # no non-identical "pretty close" pair
2025-07-02 06:41:18.798 if eqi is None:
2025-07-02 06:41:18.798 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.798 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.798 return
2025-07-02 06:41:18.798 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.798 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.798 else:
2025-07-02 06:41:18.798 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.798 eqi = None
2025-07-02 06:41:18.798
2025-07-02 06:41:18.798 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.798 # identical
2025-07-02 06:41:18.798
2025-07-02 06:41:18.798 # pump out diffs from before the synch point
2025-07-02 06:41:18.798 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.798
2025-07-02 06:41:18.798 # do intraline marking on the synch pair
2025-07-02 06:41:18.798 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.798 if eqi is None:
2025-07-02 06:41:18.798 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.799 atags = btags = ""
2025-07-02 06:41:18.799 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.799 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.799 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.799 if tag == 'replace':
2025-07-02 06:41:18.799 atags += '^' * la
2025-07-02 06:41:18.799 btags += '^' * lb
2025-07-02 06:41:18.799 elif tag == 'delete':
2025-07-02 06:41:18.799 atags += '-' * la
2025-07-02 06:41:18.799 elif tag == 'insert':
2025-07-02 06:41:18.799 btags += '+' * lb
2025-07-02 06:41:18.799 elif tag == 'equal':
2025-07-02 06:41:18.799 atags += ' ' * la
2025-07-02 06:41:18.799 btags += ' ' * lb
2025-07-02 06:41:18.799 else:
2025-07-02 06:41:18.799 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.799 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.799 else:
2025-07-02 06:41:18.800 # the synch pair is identical
2025-07-02 06:41:18.800 yield ' ' + aelt
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800 # pump out diffs from after the synch point
2025-07-02 06:41:18.800 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.800 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.800 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.800 alo = 460, ahi = 1101
2025-07-02 06:41:18.800 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.800 blo = 460, bhi = 1101
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.800 g = []
2025-07-02 06:41:18.800 if alo < ahi:
2025-07-02 06:41:18.800 if blo < bhi:
2025-07-02 06:41:18.801 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.801 else:
2025-07-02 06:41:18.801 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.801 elif blo < bhi:
2025-07-02 06:41:18.801 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 > yield from g
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.801 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.801 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.801 alo = 460, ahi = 1101
2025-07-02 06:41:18.801 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.801 blo = 460, bhi = 1101
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.801 r"""
2025-07-02 06:41:18.801 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.801 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.802 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.802 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.802
2025-07-02 06:41:18.802 Example:
2025-07-02 06:41:18.802
2025-07-02 06:41:18.802 >>> d = Differ()
2025-07-02 06:41:18.802 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.802 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.802 >>> print(''.join(results), end="")
2025-07-02 06:41:18.802 - abcDefghiJkl
2025-07-02 06:41:18.802 + abcdefGhijkl
2025-07-02 06:41:18.802 """
2025-07-02 06:41:18.802
2025-07-02 06:41:18.802 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.802 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.802 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.802 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.802 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.803
2025-07-02 06:41:18.803 # search for the pair that matches best without being identical
2025-07-02 06:41:18.803 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.803 # on junk -- unless we have to)
2025-07-02 06:41:18.803 for j in range(blo, bhi):
2025-07-02 06:41:18.803 bj = b[j]
2025-07-02 06:41:18.803 cruncher.set_seq2(bj)
2025-07-02 06:41:18.803 for i in range(alo, ahi):
2025-07-02 06:41:18.803 ai = a[i]
2025-07-02 06:41:18.803 if ai == bj:
2025-07-02 06:41:18.803 if eqi is None:
2025-07-02 06:41:18.803 eqi, eqj = i, j
2025-07-02 06:41:18.803 continue
2025-07-02 06:41:18.803 cruncher.set_seq1(ai)
2025-07-02 06:41:18.803 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.803 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.803 # compares by a factor of 3.
2025-07-02 06:41:18.803 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.803 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.803 # of the computation is cached by cruncher
2025-07-02 06:41:18.804 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.804 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.804 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.804 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.804 if best_ratio < cutoff:
2025-07-02 06:41:18.804 # no non-identical "pretty close" pair
2025-07-02 06:41:18.804 if eqi is None:
2025-07-02 06:41:18.804 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.804 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.804 return
2025-07-02 06:41:18.804 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.804 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.804 else:
2025-07-02 06:41:18.804 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.804 eqi = None
2025-07-02 06:41:18.804
2025-07-02 06:41:18.804 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.804 # identical
2025-07-02 06:41:18.804
2025-07-02 06:41:18.804 # pump out diffs from before the synch point
2025-07-02 06:41:18.804 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.805
2025-07-02 06:41:18.805 # do intraline marking on the synch pair
2025-07-02 06:41:18.805 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.805 if eqi is None:
2025-07-02 06:41:18.805 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.805 atags = btags = ""
2025-07-02 06:41:18.805 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.805 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.805 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.805 if tag == 'replace':
2025-07-02 06:41:18.805 atags += '^' * la
2025-07-02 06:41:18.805 btags += '^' * lb
2025-07-02 06:41:18.805 elif tag == 'delete':
2025-07-02 06:41:18.805 atags += '-' * la
2025-07-02 06:41:18.805 elif tag == 'insert':
2025-07-02 06:41:18.805 btags += '+' * lb
2025-07-02 06:41:18.806 elif tag == 'equal':
2025-07-02 06:41:18.806 atags += ' ' * la
2025-07-02 06:41:18.806 btags += ' ' * lb
2025-07-02 06:41:18.806 else:
2025-07-02 06:41:18.806 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.806 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.806 else:
2025-07-02 06:41:18.806 # the synch pair is identical
2025-07-02 06:41:18.806 yield ' ' + aelt
2025-07-02 06:41:18.806
2025-07-02 06:41:18.806 # pump out diffs from after the synch point
2025-07-02 06:41:18.806 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.806
2025-07-02 06:41:18.806 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.806 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.806
2025-07-02 06:41:18.806 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.806 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.806 alo = 461, ahi = 1101
2025-07-02 06:41:18.807 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.807 blo = 461, bhi = 1101
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.807 g = []
2025-07-02 06:41:18.807 if alo < ahi:
2025-07-02 06:41:18.807 if blo < bhi:
2025-07-02 06:41:18.807 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.807 else:
2025-07-02 06:41:18.807 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.807 elif blo < bhi:
2025-07-02 06:41:18.807 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 > yield from g
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.807 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.807 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.808 alo = 461, ahi = 1101
2025-07-02 06:41:18.808 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.808 blo = 461, bhi = 1101
2025-07-02 06:41:18.808
2025-07-02 06:41:18.808 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.808 r"""
2025-07-02 06:41:18.808 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.808 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.808 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.808 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.808
2025-07-02 06:41:18.808 Example:
2025-07-02 06:41:18.808
2025-07-02 06:41:18.808 >>> d = Differ()
2025-07-02 06:41:18.808 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.808 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.808 >>> print(''.join(results), end="")
2025-07-02 06:41:18.808 - abcDefghiJkl
2025-07-02 06:41:18.808 + abcdefGhijkl
2025-07-02 06:41:18.809 """
2025-07-02 06:41:18.809
2025-07-02 06:41:18.809 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.809 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.809 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.809 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.809 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.809
2025-07-02 06:41:18.809 # search for the pair that matches best without being identical
2025-07-02 06:41:18.809 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.809 # on junk -- unless we have to)
2025-07-02 06:41:18.809 for j in range(blo, bhi):
2025-07-02 06:41:18.809 bj = b[j]
2025-07-02 06:41:18.809 cruncher.set_seq2(bj)
2025-07-02 06:41:18.809 for i in range(alo, ahi):
2025-07-02 06:41:18.809 ai = a[i]
2025-07-02 06:41:18.809 if ai == bj:
2025-07-02 06:41:18.809 if eqi is None:
2025-07-02 06:41:18.809 eqi, eqj = i, j
2025-07-02 06:41:18.810 continue
2025-07-02 06:41:18.810 cruncher.set_seq1(ai)
2025-07-02 06:41:18.810 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.810 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.810 # compares by a factor of 3.
2025-07-02 06:41:18.810 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.810 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.810 # of the computation is cached by cruncher
2025-07-02 06:41:18.810 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.810 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.810 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.810 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.810 if best_ratio < cutoff:
2025-07-02 06:41:18.810 # no non-identical "pretty close" pair
2025-07-02 06:41:18.810 if eqi is None:
2025-07-02 06:41:18.810 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.810 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.810 return
2025-07-02 06:41:18.810 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.810 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.811 else:
2025-07-02 06:41:18.811 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.811 eqi = None
2025-07-02 06:41:18.811
2025-07-02 06:41:18.811 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.811 # identical
2025-07-02 06:41:18.811
2025-07-02 06:41:18.811 # pump out diffs from before the synch point
2025-07-02 06:41:18.811 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.811
2025-07-02 06:41:18.811 # do intraline marking on the synch pair
2025-07-02 06:41:18.811 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.811 if eqi is None:
2025-07-02 06:41:18.811 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.811 atags = btags = ""
2025-07-02 06:41:18.811 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.811 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.811 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.811 if tag == 'replace':
2025-07-02 06:41:18.811 atags += '^' * la
2025-07-02 06:41:18.811 btags += '^' * lb
2025-07-02 06:41:18.812 elif tag == 'delete':
2025-07-02 06:41:18.812 atags += '-' * la
2025-07-02 06:41:18.812 elif tag == 'insert':
2025-07-02 06:41:18.812 btags += '+' * lb
2025-07-02 06:41:18.812 elif tag == 'equal':
2025-07-02 06:41:18.812 atags += ' ' * la
2025-07-02 06:41:18.812 btags += ' ' * lb
2025-07-02 06:41:18.812 else:
2025-07-02 06:41:18.812 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.812 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.812 else:
2025-07-02 06:41:18.812 # the synch pair is identical
2025-07-02 06:41:18.812 yield ' ' + aelt
2025-07-02 06:41:18.812
2025-07-02 06:41:18.812 # pump out diffs from after the synch point
2025-07-02 06:41:18.812 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.812
2025-07-02 06:41:18.812 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.812 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.812
2025-07-02 06:41:18.813 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.813 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.813 alo = 462, ahi = 1101
2025-07-02 06:41:18.813 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.813 blo = 462, bhi = 1101
2025-07-02 06:41:18.813
2025-07-02 06:41:18.813 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.813 g = []
2025-07-02 06:41:18.813 if alo < ahi:
2025-07-02 06:41:18.813 if blo < bhi:
2025-07-02 06:41:18.813 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.813 else:
2025-07-02 06:41:18.813 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.813 elif blo < bhi:
2025-07-02 06:41:18.813 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.813
2025-07-02 06:41:18.813 > yield from g
2025-07-02 06:41:18.813
2025-07-02 06:41:18.813 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.813 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.814 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.814 alo = 462, ahi = 1101
2025-07-02 06:41:18.814 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.814 blo = 462, bhi = 1101
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.814 r"""
2025-07-02 06:41:18.814 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.814 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.814 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.814 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814 Example:
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814 >>> d = Differ()
2025-07-02 06:41:18.814 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.814 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.815 >>> print(''.join(results), end="")
2025-07-02 06:41:18.815 - abcDefghiJkl
2025-07-02 06:41:18.815 + abcdefGhijkl
2025-07-02 06:41:18.815 """
2025-07-02 06:41:18.815
2025-07-02 06:41:18.815 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.815 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.815 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.815 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.815 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.815
2025-07-02 06:41:18.815 # search for the pair that matches best without being identical
2025-07-02 06:41:18.815 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.815 # on junk -- unless we have to)
2025-07-02 06:41:18.815 for j in range(blo, bhi):
2025-07-02 06:41:18.815 bj = b[j]
2025-07-02 06:41:18.815 cruncher.set_seq2(bj)
2025-07-02 06:41:18.816 for i in range(alo, ahi):
2025-07-02 06:41:18.816 ai = a[i]
2025-07-02 06:41:18.816 if ai == bj:
2025-07-02 06:41:18.816 if eqi is None:
2025-07-02 06:41:18.816 eqi, eqj = i, j
2025-07-02 06:41:18.816 continue
2025-07-02 06:41:18.816 cruncher.set_seq1(ai)
2025-07-02 06:41:18.816 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.816 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.816 # compares by a factor of 3.
2025-07-02 06:41:18.816 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.816 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.816 # of the computation is cached by cruncher
2025-07-02 06:41:18.816 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.816 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.816 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.816 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.816 if best_ratio < cutoff:
2025-07-02 06:41:18.816 # no non-identical "pretty close" pair
2025-07-02 06:41:18.817 if eqi is None:
2025-07-02 06:41:18.817 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.817 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.817 return
2025-07-02 06:41:18.817 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.817 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.817 else:
2025-07-02 06:41:18.817 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.817 eqi = None
2025-07-02 06:41:18.817
2025-07-02 06:41:18.817 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.817 # identical
2025-07-02 06:41:18.817
2025-07-02 06:41:18.817 # pump out diffs from before the synch point
2025-07-02 06:41:18.817 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.817
2025-07-02 06:41:18.817 # do intraline marking on the synch pair
2025-07-02 06:41:18.817 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.817 if eqi is None:
2025-07-02 06:41:18.818 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.818 atags = btags = ""
2025-07-02 06:41:18.818 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.818 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.818 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.818 if tag == 'replace':
2025-07-02 06:41:18.818 atags += '^' * la
2025-07-02 06:41:18.818 btags += '^' * lb
2025-07-02 06:41:18.818 elif tag == 'delete':
2025-07-02 06:41:18.818 atags += '-' * la
2025-07-02 06:41:18.818 elif tag == 'insert':
2025-07-02 06:41:18.818 btags += '+' * lb
2025-07-02 06:41:18.818 elif tag == 'equal':
2025-07-02 06:41:18.818 atags += ' ' * la
2025-07-02 06:41:18.818 btags += ' ' * lb
2025-07-02 06:41:18.818 else:
2025-07-02 06:41:18.818 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.818 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.818 else:
2025-07-02 06:41:18.818 # the synch pair is identical
2025-07-02 06:41:18.819 yield ' ' + aelt
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819 # pump out diffs from after the synch point
2025-07-02 06:41:18.819 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.819 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.819 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.819 alo = 463, ahi = 1101
2025-07-02 06:41:18.819 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.819 blo = 463, bhi = 1101
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.819 g = []
2025-07-02 06:41:18.819 if alo < ahi:
2025-07-02 06:41:18.819 if blo < bhi:
2025-07-02 06:41:18.819 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.819 else:
2025-07-02 06:41:18.820 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.820 elif blo < bhi:
2025-07-02 06:41:18.820 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 > yield from g
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.820 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.820 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.820 alo = 463, ahi = 1101
2025-07-02 06:41:18.820 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.820 blo = 463, bhi = 1101
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.820 r"""
2025-07-02 06:41:18.820 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.820 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.820 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.821 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821 Example:
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821 >>> d = Differ()
2025-07-02 06:41:18.821 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.821 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.821 >>> print(''.join(results), end="")
2025-07-02 06:41:18.821 - abcDefghiJkl
2025-07-02 06:41:18.821 + abcdefGhijkl
2025-07-02 06:41:18.821 """
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.821 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.821 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.821 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.821 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821 # search for the pair that matches best without being identical
2025-07-02 06:41:18.822 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.822 # on junk -- unless we have to)
2025-07-02 06:41:18.822 for j in range(blo, bhi):
2025-07-02 06:41:18.822 bj = b[j]
2025-07-02 06:41:18.822 cruncher.set_seq2(bj)
2025-07-02 06:41:18.822 for i in range(alo, ahi):
2025-07-02 06:41:18.822 ai = a[i]
2025-07-02 06:41:18.822 if ai == bj:
2025-07-02 06:41:18.822 if eqi is None:
2025-07-02 06:41:18.822 eqi, eqj = i, j
2025-07-02 06:41:18.822 continue
2025-07-02 06:41:18.822 cruncher.set_seq1(ai)
2025-07-02 06:41:18.822 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.822 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.822 # compares by a factor of 3.
2025-07-02 06:41:18.822 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.822 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.822 # of the computation is cached by cruncher
2025-07-02 06:41:18.823 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.823 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.823 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.823 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.823 if best_ratio < cutoff:
2025-07-02 06:41:18.823 # no non-identical "pretty close" pair
2025-07-02 06:41:18.823 if eqi is None:
2025-07-02 06:41:18.823 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.823 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.823 return
2025-07-02 06:41:18.823 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.823 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.823 else:
2025-07-02 06:41:18.823 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.823 eqi = None
2025-07-02 06:41:18.823
2025-07-02 06:41:18.823 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.823 # identical
2025-07-02 06:41:18.823
2025-07-02 06:41:18.824 # pump out diffs from before the synch point
2025-07-02 06:41:18.824 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.824
2025-07-02 06:41:18.824 # do intraline marking on the synch pair
2025-07-02 06:41:18.824 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.824 if eqi is None:
2025-07-02 06:41:18.824 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.824 atags = btags = ""
2025-07-02 06:41:18.824 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.824 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.824 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.824 if tag == 'replace':
2025-07-02 06:41:18.824 atags += '^' * la
2025-07-02 06:41:18.824 btags += '^' * lb
2025-07-02 06:41:18.824 elif tag == 'delete':
2025-07-02 06:41:18.824 atags += '-' * la
2025-07-02 06:41:18.824 elif tag == 'insert':
2025-07-02 06:41:18.824 btags += '+' * lb
2025-07-02 06:41:18.824 elif tag == 'equal':
2025-07-02 06:41:18.824 atags += ' ' * la
2025-07-02 06:41:18.825 btags += ' ' * lb
2025-07-02 06:41:18.825 else:
2025-07-02 06:41:18.825 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.825 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.825 else:
2025-07-02 06:41:18.825 # the synch pair is identical
2025-07-02 06:41:18.825 yield ' ' + aelt
2025-07-02 06:41:18.825
2025-07-02 06:41:18.825 # pump out diffs from after the synch point
2025-07-02 06:41:18.825 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.825
2025-07-02 06:41:18.825 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.825 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.825
2025-07-02 06:41:18.825 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.825 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.825 alo = 466, ahi = 1101
2025-07-02 06:41:18.825 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.825 blo = 466, bhi = 1101
2025-07-02 06:41:18.825
2025-07-02 06:41:18.826 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.826 g = []
2025-07-02 06:41:18.826 if alo < ahi:
2025-07-02 06:41:18.826 if blo < bhi:
2025-07-02 06:41:18.826 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.826 else:
2025-07-02 06:41:18.826 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.826 elif blo < bhi:
2025-07-02 06:41:18.826 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.826
2025-07-02 06:41:18.826 > yield from g
2025-07-02 06:41:18.826
2025-07-02 06:41:18.826 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.826 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.826
2025-07-02 06:41:18.826 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.826 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.826 alo = 466, ahi = 1101
2025-07-02 06:41:18.826 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.826 blo = 466, bhi = 1101
2025-07-02 06:41:18.827
2025-07-02 06:41:18.827 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.827 r"""
2025-07-02 06:41:18.827 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.827 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.827 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.827 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.827
2025-07-02 06:41:18.827 Example:
2025-07-02 06:41:18.827
2025-07-02 06:41:18.827 >>> d = Differ()
2025-07-02 06:41:18.827 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.827 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.827 >>> print(''.join(results), end="")
2025-07-02 06:41:18.827 - abcDefghiJkl
2025-07-02 06:41:18.827 + abcdefGhijkl
2025-07-02 06:41:18.827 """
2025-07-02 06:41:18.827
2025-07-02 06:41:18.828 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.828 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.828 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.828 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.828 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.828
2025-07-02 06:41:18.828 # search for the pair that matches best without being identical
2025-07-02 06:41:18.828 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.828 # on junk -- unless we have to)
2025-07-02 06:41:18.828 for j in range(blo, bhi):
2025-07-02 06:41:18.828 bj = b[j]
2025-07-02 06:41:18.828 cruncher.set_seq2(bj)
2025-07-02 06:41:18.828 for i in range(alo, ahi):
2025-07-02 06:41:18.828 ai = a[i]
2025-07-02 06:41:18.828 if ai == bj:
2025-07-02 06:41:18.828 if eqi is None:
2025-07-02 06:41:18.828 eqi, eqj = i, j
2025-07-02 06:41:18.828 continue
2025-07-02 06:41:18.828 cruncher.set_seq1(ai)
2025-07-02 06:41:18.828 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.828 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.829 # compares by a factor of 3.
2025-07-02 06:41:18.829 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.829 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.829 # of the computation is cached by cruncher
2025-07-02 06:41:18.829 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.829 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.829 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.829 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.829 if best_ratio < cutoff:
2025-07-02 06:41:18.829 # no non-identical "pretty close" pair
2025-07-02 06:41:18.829 if eqi is None:
2025-07-02 06:41:18.829 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.829 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.829 return
2025-07-02 06:41:18.829 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.829 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.829 else:
2025-07-02 06:41:18.829 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.829 eqi = None
2025-07-02 06:41:18.829
2025-07-02 06:41:18.830 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.830 # identical
2025-07-02 06:41:18.830
2025-07-02 06:41:18.830 # pump out diffs from before the synch point
2025-07-02 06:41:18.830 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.830
2025-07-02 06:41:18.830 # do intraline marking on the synch pair
2025-07-02 06:41:18.830 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.830 if eqi is None:
2025-07-02 06:41:18.830 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.830 atags = btags = ""
2025-07-02 06:41:18.830 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.830 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.830 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.830 if tag == 'replace':
2025-07-02 06:41:18.830 atags += '^' * la
2025-07-02 06:41:18.830 btags += '^' * lb
2025-07-02 06:41:18.830 elif tag == 'delete':
2025-07-02 06:41:18.830 atags += '-' * la
2025-07-02 06:41:18.830 elif tag == 'insert':
2025-07-02 06:41:18.831 btags += '+' * lb
2025-07-02 06:41:18.831 elif tag == 'equal':
2025-07-02 06:41:18.831 atags += ' ' * la
2025-07-02 06:41:18.831 btags += ' ' * lb
2025-07-02 06:41:18.831 else:
2025-07-02 06:41:18.831 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.831 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.831 else:
2025-07-02 06:41:18.831 # the synch pair is identical
2025-07-02 06:41:18.831 yield ' ' + aelt
2025-07-02 06:41:18.831
2025-07-02 06:41:18.831 # pump out diffs from after the synch point
2025-07-02 06:41:18.831 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.831
2025-07-02 06:41:18.831 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.831 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.831
2025-07-02 06:41:18.832 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.832 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.832 alo = 467, ahi = 1101
2025-07-02 06:41:18.832 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.832 blo = 467, bhi = 1101
2025-07-02 06:41:18.832
2025-07-02 06:41:18.832 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.832 g = []
2025-07-02 06:41:18.832 if alo < ahi:
2025-07-02 06:41:18.832 if blo < bhi:
2025-07-02 06:41:18.832 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.832 else:
2025-07-02 06:41:18.832 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.832 elif blo < bhi:
2025-07-02 06:41:18.832 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.832
2025-07-02 06:41:18.832 > yield from g
2025-07-02 06:41:18.832
2025-07-02 06:41:18.832 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.833 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.833 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.833 alo = 467, ahi = 1101
2025-07-02 06:41:18.833 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.833 blo = 467, bhi = 1101
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.833 r"""
2025-07-02 06:41:18.833 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.833 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.833 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.833 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833 Example:
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833 >>> d = Differ()
2025-07-02 06:41:18.833 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.834 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.834 >>> print(''.join(results), end="")
2025-07-02 06:41:18.834 - abcDefghiJkl
2025-07-02 06:41:18.834 + abcdefGhijkl
2025-07-02 06:41:18.834 """
2025-07-02 06:41:18.834
2025-07-02 06:41:18.834 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.834 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.834 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.834 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.834 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.834
2025-07-02 06:41:18.834 # search for the pair that matches best without being identical
2025-07-02 06:41:18.834 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.834 # on junk -- unless we have to)
2025-07-02 06:41:18.834 for j in range(blo, bhi):
2025-07-02 06:41:18.834 bj = b[j]
2025-07-02 06:41:18.834 cruncher.set_seq2(bj)
2025-07-02 06:41:18.835 for i in range(alo, ahi):
2025-07-02 06:41:18.835 ai = a[i]
2025-07-02 06:41:18.835 if ai == bj:
2025-07-02 06:41:18.835 if eqi is None:
2025-07-02 06:41:18.835 eqi, eqj = i, j
2025-07-02 06:41:18.835 continue
2025-07-02 06:41:18.835 cruncher.set_seq1(ai)
2025-07-02 06:41:18.835 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.835 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.835 # compares by a factor of 3.
2025-07-02 06:41:18.835 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.835 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.835 # of the computation is cached by cruncher
2025-07-02 06:41:18.835 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.835 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.835 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.835 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.836 if best_ratio < cutoff:
2025-07-02 06:41:18.836 # no non-identical "pretty close" pair
2025-07-02 06:41:18.836 if eqi is None:
2025-07-02 06:41:18.836 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.836 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.836 return
2025-07-02 06:41:18.836 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.836 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.836 else:
2025-07-02 06:41:18.836 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.836 eqi = None
2025-07-02 06:41:18.836
2025-07-02 06:41:18.836 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.836 # identical
2025-07-02 06:41:18.836
2025-07-02 06:41:18.836 # pump out diffs from before the synch point
2025-07-02 06:41:18.836 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.836
2025-07-02 06:41:18.836 # do intraline marking on the synch pair
2025-07-02 06:41:18.836 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.837 if eqi is None:
2025-07-02 06:41:18.837 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.837 atags = btags = ""
2025-07-02 06:41:18.837 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.837 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.837 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.837 if tag == 'replace':
2025-07-02 06:41:18.837 atags += '^' * la
2025-07-02 06:41:18.837 btags += '^' * lb
2025-07-02 06:41:18.837 elif tag == 'delete':
2025-07-02 06:41:18.837 atags += '-' * la
2025-07-02 06:41:18.837 elif tag == 'insert':
2025-07-02 06:41:18.837 btags += '+' * lb
2025-07-02 06:41:18.837 elif tag == 'equal':
2025-07-02 06:41:18.837 atags += ' ' * la
2025-07-02 06:41:18.837 btags += ' ' * lb
2025-07-02 06:41:18.837 else:
2025-07-02 06:41:18.837 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.837 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.837 else:
2025-07-02 06:41:18.838 # the synch pair is identical
2025-07-02 06:41:18.838 yield ' ' + aelt
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838 # pump out diffs from after the synch point
2025-07-02 06:41:18.838 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.838 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.838 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.838 alo = 468, ahi = 1101
2025-07-02 06:41:18.838 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.838 blo = 468, bhi = 1101
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.838 g = []
2025-07-02 06:41:18.838 if alo < ahi:
2025-07-02 06:41:18.838 if blo < bhi:
2025-07-02 06:41:18.838 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.839 else:
2025-07-02 06:41:18.839 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.839 elif blo < bhi:
2025-07-02 06:41:18.839 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 > yield from g
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.839 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.839 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.839 alo = 468, ahi = 1101
2025-07-02 06:41:18.839 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.839 blo = 468, bhi = 1101
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.839 r"""
2025-07-02 06:41:18.839 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.839 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.839 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.840 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.840
2025-07-02 06:41:18.840 Example:
2025-07-02 06:41:18.840
2025-07-02 06:41:18.840 >>> d = Differ()
2025-07-02 06:41:18.840 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.840 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.840 >>> print(''.join(results), end="")
2025-07-02 06:41:18.840 - abcDefghiJkl
2025-07-02 06:41:18.840 + abcdefGhijkl
2025-07-02 06:41:18.840 """
2025-07-02 06:41:18.840
2025-07-02 06:41:18.840 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.840 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.840 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.840 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.841 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.841
2025-07-02 06:41:18.841 # search for the pair that matches best without being identical
2025-07-02 06:41:18.841 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.841 # on junk -- unless we have to)
2025-07-02 06:41:18.841 for j in range(blo, bhi):
2025-07-02 06:41:18.841 bj = b[j]
2025-07-02 06:41:18.841 cruncher.set_seq2(bj)
2025-07-02 06:41:18.841 for i in range(alo, ahi):
2025-07-02 06:41:18.841 ai = a[i]
2025-07-02 06:41:18.841 if ai == bj:
2025-07-02 06:41:18.841 if eqi is None:
2025-07-02 06:41:18.841 eqi, eqj = i, j
2025-07-02 06:41:18.841 continue
2025-07-02 06:41:18.841 cruncher.set_seq1(ai)
2025-07-02 06:41:18.841 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.841 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.841 # compares by a factor of 3.
2025-07-02 06:41:18.841 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.842 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.842 # of the computation is cached by cruncher
2025-07-02 06:41:18.842 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.842 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.842 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.842 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.842 if best_ratio < cutoff:
2025-07-02 06:41:18.842 # no non-identical "pretty close" pair
2025-07-02 06:41:18.842 if eqi is None:
2025-07-02 06:41:18.842 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.842 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.842 return
2025-07-02 06:41:18.842 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.842 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.842 else:
2025-07-02 06:41:18.842 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.842 eqi = None
2025-07-02 06:41:18.842
2025-07-02 06:41:18.842 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.842 # identical
2025-07-02 06:41:18.843
2025-07-02 06:41:18.843 # pump out diffs from before the synch point
2025-07-02 06:41:18.843 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.843
2025-07-02 06:41:18.843 # do intraline marking on the synch pair
2025-07-02 06:41:18.843 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.843 if eqi is None:
2025-07-02 06:41:18.843 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.843 atags = btags = ""
2025-07-02 06:41:18.843 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.843 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.843 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.843 if tag == 'replace':
2025-07-02 06:41:18.843 atags += '^' * la
2025-07-02 06:41:18.843 btags += '^' * lb
2025-07-02 06:41:18.843 elif tag == 'delete':
2025-07-02 06:41:18.843 atags += '-' * la
2025-07-02 06:41:18.843 elif tag == 'insert':
2025-07-02 06:41:18.843 btags += '+' * lb
2025-07-02 06:41:18.844 elif tag == 'equal':
2025-07-02 06:41:18.844 atags += ' ' * la
2025-07-02 06:41:18.844 btags += ' ' * lb
2025-07-02 06:41:18.844 else:
2025-07-02 06:41:18.844 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.844 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.844 else:
2025-07-02 06:41:18.844 # the synch pair is identical
2025-07-02 06:41:18.844 yield ' ' + aelt
2025-07-02 06:41:18.844
2025-07-02 06:41:18.844 # pump out diffs from after the synch point
2025-07-02 06:41:18.844 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.844
2025-07-02 06:41:18.844 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.844 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.844
2025-07-02 06:41:18.844 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.844 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.844 alo = 469, ahi = 1101
2025-07-02 06:41:18.844 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.845 blo = 469, bhi = 1101
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.845 g = []
2025-07-02 06:41:18.845 if alo < ahi:
2025-07-02 06:41:18.845 if blo < bhi:
2025-07-02 06:41:18.845 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.845 else:
2025-07-02 06:41:18.845 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.845 elif blo < bhi:
2025-07-02 06:41:18.845 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 > yield from g
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.845 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.845 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.845 alo = 469, ahi = 1101
2025-07-02 06:41:18.846 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.846 blo = 469, bhi = 1101
2025-07-02 06:41:18.846
2025-07-02 06:41:18.846 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.846 r"""
2025-07-02 06:41:18.846 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.846 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.846 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.846 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.846
2025-07-02 06:41:18.846 Example:
2025-07-02 06:41:18.846
2025-07-02 06:41:18.846 >>> d = Differ()
2025-07-02 06:41:18.846 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.846 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.846 >>> print(''.join(results), end="")
2025-07-02 06:41:18.846 - abcDefghiJkl
2025-07-02 06:41:18.846 + abcdefGhijkl
2025-07-02 06:41:18.847 """
2025-07-02 06:41:18.847
2025-07-02 06:41:18.847 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.847 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.847 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.847 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.847 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.847
2025-07-02 06:41:18.847 # search for the pair that matches best without being identical
2025-07-02 06:41:18.847 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.847 # on junk -- unless we have to)
2025-07-02 06:41:18.847 for j in range(blo, bhi):
2025-07-02 06:41:18.847 bj = b[j]
2025-07-02 06:41:18.847 cruncher.set_seq2(bj)
2025-07-02 06:41:18.847 for i in range(alo, ahi):
2025-07-02 06:41:18.847 ai = a[i]
2025-07-02 06:41:18.847 if ai == bj:
2025-07-02 06:41:18.847 if eqi is None:
2025-07-02 06:41:18.848 eqi, eqj = i, j
2025-07-02 06:41:18.848 continue
2025-07-02 06:41:18.848 cruncher.set_seq1(ai)
2025-07-02 06:41:18.848 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.848 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.848 # compares by a factor of 3.
2025-07-02 06:41:18.848 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.848 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.848 # of the computation is cached by cruncher
2025-07-02 06:41:18.848 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.848 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.848 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.848 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.848 if best_ratio < cutoff:
2025-07-02 06:41:18.848 # no non-identical "pretty close" pair
2025-07-02 06:41:18.848 if eqi is None:
2025-07-02 06:41:18.848 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.848 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.848 return
2025-07-02 06:41:18.848 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.849 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.849 else:
2025-07-02 06:41:18.849 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.849 eqi = None
2025-07-02 06:41:18.849
2025-07-02 06:41:18.849 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.849 # identical
2025-07-02 06:41:18.849
2025-07-02 06:41:18.849 # pump out diffs from before the synch point
2025-07-02 06:41:18.849 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.849
2025-07-02 06:41:18.849 # do intraline marking on the synch pair
2025-07-02 06:41:18.849 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.849 if eqi is None:
2025-07-02 06:41:18.849 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.849 atags = btags = ""
2025-07-02 06:41:18.849 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.849 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.849 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.850 if tag == 'replace':
2025-07-02 06:41:18.850 atags += '^' * la
2025-07-02 06:41:18.850 btags += '^' * lb
2025-07-02 06:41:18.850 elif tag == 'delete':
2025-07-02 06:41:18.850 atags += '-' * la
2025-07-02 06:41:18.850 elif tag == 'insert':
2025-07-02 06:41:18.850 btags += '+' * lb
2025-07-02 06:41:18.850 elif tag == 'equal':
2025-07-02 06:41:18.850 atags += ' ' * la
2025-07-02 06:41:18.850 btags += ' ' * lb
2025-07-02 06:41:18.850 else:
2025-07-02 06:41:18.850 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.850 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.850 else:
2025-07-02 06:41:18.850 # the synch pair is identical
2025-07-02 06:41:18.850 yield ' ' + aelt
2025-07-02 06:41:18.850
2025-07-02 06:41:18.850 # pump out diffs from after the synch point
2025-07-02 06:41:18.850 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.851
2025-07-02 06:41:18.851 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.851 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.851
2025-07-02 06:41:18.851 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.851 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.851 alo = 470, ahi = 1101
2025-07-02 06:41:18.851 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.851 blo = 470, bhi = 1101
2025-07-02 06:41:18.851
2025-07-02 06:41:18.851 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.851 g = []
2025-07-02 06:41:18.851 if alo < ahi:
2025-07-02 06:41:18.851 if blo < bhi:
2025-07-02 06:41:18.851 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.851 else:
2025-07-02 06:41:18.851 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.851 elif blo < bhi:
2025-07-02 06:41:18.851 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.851
2025-07-02 06:41:18.852 > yield from g
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.852 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.852 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.852 alo = 470, ahi = 1101
2025-07-02 06:41:18.852 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.852 blo = 470, bhi = 1101
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.852 r"""
2025-07-02 06:41:18.852 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.852 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.852 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.852 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852 Example:
2025-07-02 06:41:18.852
2025-07-02 06:41:18.853 >>> d = Differ()
2025-07-02 06:41:18.853 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.853 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.853 >>> print(''.join(results), end="")
2025-07-02 06:41:18.853 - abcDefghiJkl
2025-07-02 06:41:18.853 + abcdefGhijkl
2025-07-02 06:41:18.853 """
2025-07-02 06:41:18.853
2025-07-02 06:41:18.853 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.853 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.853 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.853 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.853 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.853
2025-07-02 06:41:18.853 # search for the pair that matches best without being identical
2025-07-02 06:41:18.853 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.853 # on junk -- unless we have to)
2025-07-02 06:41:18.853 for j in range(blo, bhi):
2025-07-02 06:41:18.854 bj = b[j]
2025-07-02 06:41:18.854 cruncher.set_seq2(bj)
2025-07-02 06:41:18.854 for i in range(alo, ahi):
2025-07-02 06:41:18.854 ai = a[i]
2025-07-02 06:41:18.854 if ai == bj:
2025-07-02 06:41:18.854 if eqi is None:
2025-07-02 06:41:18.854 eqi, eqj = i, j
2025-07-02 06:41:18.854 continue
2025-07-02 06:41:18.854 cruncher.set_seq1(ai)
2025-07-02 06:41:18.854 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.854 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.854 # compares by a factor of 3.
2025-07-02 06:41:18.854 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.854 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.854 # of the computation is cached by cruncher
2025-07-02 06:41:18.854 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.854 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.854 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.854 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.854 if best_ratio < cutoff:
2025-07-02 06:41:18.855 # no non-identical "pretty close" pair
2025-07-02 06:41:18.855 if eqi is None:
2025-07-02 06:41:18.855 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.855 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.855 return
2025-07-02 06:41:18.855 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.855 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.855 else:
2025-07-02 06:41:18.855 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.855 eqi = None
2025-07-02 06:41:18.855
2025-07-02 06:41:18.855 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.855 # identical
2025-07-02 06:41:18.855
2025-07-02 06:41:18.855 # pump out diffs from before the synch point
2025-07-02 06:41:18.855 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.855
2025-07-02 06:41:18.855 # do intraline marking on the synch pair
2025-07-02 06:41:18.855 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.855 if eqi is None:
2025-07-02 06:41:18.855 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.856 atags = btags = ""
2025-07-02 06:41:18.856 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.856 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.856 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.856 if tag == 'replace':
2025-07-02 06:41:18.856 atags += '^' * la
2025-07-02 06:41:18.856 btags += '^' * lb
2025-07-02 06:41:18.856 elif tag == 'delete':
2025-07-02 06:41:18.856 atags += '-' * la
2025-07-02 06:41:18.856 elif tag == 'insert':
2025-07-02 06:41:18.856 btags += '+' * lb
2025-07-02 06:41:18.856 elif tag == 'equal':
2025-07-02 06:41:18.856 atags += ' ' * la
2025-07-02 06:41:18.856 btags += ' ' * lb
2025-07-02 06:41:18.856 else:
2025-07-02 06:41:18.856 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.856 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.856 else:
2025-07-02 06:41:18.856 # the synch pair is identical
2025-07-02 06:41:18.856 yield ' ' + aelt
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857 # pump out diffs from after the synch point
2025-07-02 06:41:18.857 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.857 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.857 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.857 alo = 471, ahi = 1101
2025-07-02 06:41:18.857 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.857 blo = 471, bhi = 1101
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.857 g = []
2025-07-02 06:41:18.857 if alo < ahi:
2025-07-02 06:41:18.857 if blo < bhi:
2025-07-02 06:41:18.857 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.857 else:
2025-07-02 06:41:18.858 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.858 elif blo < bhi:
2025-07-02 06:41:18.858 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 > yield from g
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.858 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.858 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.858 alo = 471, ahi = 1101
2025-07-02 06:41:18.858 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.858 blo = 471, bhi = 1101
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.858 r"""
2025-07-02 06:41:18.858 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.858 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.858 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.859 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.859
2025-07-02 06:41:18.859 Example:
2025-07-02 06:41:18.859
2025-07-02 06:41:18.859 >>> d = Differ()
2025-07-02 06:41:18.859 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.859 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.859 >>> print(''.join(results), end="")
2025-07-02 06:41:18.859 - abcDefghiJkl
2025-07-02 06:41:18.859 + abcdefGhijkl
2025-07-02 06:41:18.859 """
2025-07-02 06:41:18.859
2025-07-02 06:41:18.859 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.859 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.859 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.859 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.860 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.860
2025-07-02 06:41:18.860 # search for the pair that matches best without being identical
2025-07-02 06:41:18.860 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.860 # on junk -- unless we have to)
2025-07-02 06:41:18.860 for j in range(blo, bhi):
2025-07-02 06:41:18.860 bj = b[j]
2025-07-02 06:41:18.860 cruncher.set_seq2(bj)
2025-07-02 06:41:18.860 for i in range(alo, ahi):
2025-07-02 06:41:18.860 ai = a[i]
2025-07-02 06:41:18.860 if ai == bj:
2025-07-02 06:41:18.860 if eqi is None:
2025-07-02 06:41:18.860 eqi, eqj = i, j
2025-07-02 06:41:18.860 continue
2025-07-02 06:41:18.860 cruncher.set_seq1(ai)
2025-07-02 06:41:18.860 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.860 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.860 # compares by a factor of 3.
2025-07-02 06:41:18.860 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.861 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.861 # of the computation is cached by cruncher
2025-07-02 06:41:18.861 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.861 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.861 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.861 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.861 if best_ratio < cutoff:
2025-07-02 06:41:18.861 # no non-identical "pretty close" pair
2025-07-02 06:41:18.861 if eqi is None:
2025-07-02 06:41:18.861 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.861 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.861 return
2025-07-02 06:41:18.861 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.861 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.861 else:
2025-07-02 06:41:18.861 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.861 eqi = None
2025-07-02 06:41:18.861
2025-07-02 06:41:18.861 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.862 # identical
2025-07-02 06:41:18.862
2025-07-02 06:41:18.862 # pump out diffs from before the synch point
2025-07-02 06:41:18.862 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.862
2025-07-02 06:41:18.862 # do intraline marking on the synch pair
2025-07-02 06:41:18.862 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.862 if eqi is None:
2025-07-02 06:41:18.862 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.862 atags = btags = ""
2025-07-02 06:41:18.862 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.862 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.862 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.862 if tag == 'replace':
2025-07-02 06:41:18.862 atags += '^' * la
2025-07-02 06:41:18.862 btags += '^' * lb
2025-07-02 06:41:18.862 elif tag == 'delete':
2025-07-02 06:41:18.862 atags += '-' * la
2025-07-02 06:41:18.862 elif tag == 'insert':
2025-07-02 06:41:18.862 btags += '+' * lb
2025-07-02 06:41:18.863 elif tag == 'equal':
2025-07-02 06:41:18.863 atags += ' ' * la
2025-07-02 06:41:18.863 btags += ' ' * lb
2025-07-02 06:41:18.863 else:
2025-07-02 06:41:18.863 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.863 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.863 else:
2025-07-02 06:41:18.863 # the synch pair is identical
2025-07-02 06:41:18.863 yield ' ' + aelt
2025-07-02 06:41:18.863
2025-07-02 06:41:18.863 # pump out diffs from after the synch point
2025-07-02 06:41:18.863 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.863
2025-07-02 06:41:18.863 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.863 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.864 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.864 alo = 472, ahi = 1101
2025-07-02 06:41:18.864 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.864 blo = 472, bhi = 1101
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.864 g = []
2025-07-02 06:41:18.864 if alo < ahi:
2025-07-02 06:41:18.864 if blo < bhi:
2025-07-02 06:41:18.864 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.864 else:
2025-07-02 06:41:18.864 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.864 elif blo < bhi:
2025-07-02 06:41:18.864 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 > yield from g
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.865 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.865
2025-07-02 06:41:18.865 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.865 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.865 alo = 472, ahi = 1101
2025-07-02 06:41:18.865 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.865 blo = 472, bhi = 1101
2025-07-02 06:41:18.865
2025-07-02 06:41:18.865 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.865 r"""
2025-07-02 06:41:18.865 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.865 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.865 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.865 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.865
2025-07-02 06:41:18.865 Example:
2025-07-02 06:41:18.865
2025-07-02 06:41:18.866 >>> d = Differ()
2025-07-02 06:41:18.866 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.866 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.866 >>> print(''.join(results), end="")
2025-07-02 06:41:18.866 - abcDefghiJkl
2025-07-02 06:41:18.866 + abcdefGhijkl
2025-07-02 06:41:18.866 """
2025-07-02 06:41:18.866
2025-07-02 06:41:18.866 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.866 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.866 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.866 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.866 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.866
2025-07-02 06:41:18.866 # search for the pair that matches best without being identical
2025-07-02 06:41:18.866 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.866 # on junk -- unless we have to)
2025-07-02 06:41:18.867 for j in range(blo, bhi):
2025-07-02 06:41:18.867 bj = b[j]
2025-07-02 06:41:18.867 cruncher.set_seq2(bj)
2025-07-02 06:41:18.867 for i in range(alo, ahi):
2025-07-02 06:41:18.867 ai = a[i]
2025-07-02 06:41:18.867 if ai == bj:
2025-07-02 06:41:18.867 if eqi is None:
2025-07-02 06:41:18.867 eqi, eqj = i, j
2025-07-02 06:41:18.867 continue
2025-07-02 06:41:18.867 cruncher.set_seq1(ai)
2025-07-02 06:41:18.867 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.867 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.867 # compares by a factor of 3.
2025-07-02 06:41:18.867 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.867 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.867 # of the computation is cached by cruncher
2025-07-02 06:41:18.867 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.867 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.868 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.868 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.868 if best_ratio < cutoff:
2025-07-02 06:41:18.868 # no non-identical "pretty close" pair
2025-07-02 06:41:18.868 if eqi is None:
2025-07-02 06:41:18.868 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.868 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.868 return
2025-07-02 06:41:18.868 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.868 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.868 else:
2025-07-02 06:41:18.868 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.868 eqi = None
2025-07-02 06:41:18.868
2025-07-02 06:41:18.868 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.868 # identical
2025-07-02 06:41:18.868
2025-07-02 06:41:18.868 # pump out diffs from before the synch point
2025-07-02 06:41:18.868 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.869
2025-07-02 06:41:18.869 # do intraline marking on the synch pair
2025-07-02 06:41:18.869 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.869 if eqi is None:
2025-07-02 06:41:18.869 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.869 atags = btags = ""
2025-07-02 06:41:18.869 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.869 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.869 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.869 if tag == 'replace':
2025-07-02 06:41:18.869 atags += '^' * la
2025-07-02 06:41:18.869 btags += '^' * lb
2025-07-02 06:41:18.869 elif tag == 'delete':
2025-07-02 06:41:18.869 atags += '-' * la
2025-07-02 06:41:18.869 elif tag == 'insert':
2025-07-02 06:41:18.869 btags += '+' * lb
2025-07-02 06:41:18.869 elif tag == 'equal':
2025-07-02 06:41:18.869 atags += ' ' * la
2025-07-02 06:41:18.869 btags += ' ' * lb
2025-07-02 06:41:18.869 else:
2025-07-02 06:41:18.869 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.870 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.870 else:
2025-07-02 06:41:18.870 # the synch pair is identical
2025-07-02 06:41:18.870 yield ' ' + aelt
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870 # pump out diffs from after the synch point
2025-07-02 06:41:18.870 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.870 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.870 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.870 alo = 473, ahi = 1101
2025-07-02 06:41:18.870 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.870 blo = 473, bhi = 1101
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.870 g = []
2025-07-02 06:41:18.870 if alo < ahi:
2025-07-02 06:41:18.871 if blo < bhi:
2025-07-02 06:41:18.871 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.871 else:
2025-07-02 06:41:18.871 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.871 elif blo < bhi:
2025-07-02 06:41:18.871 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 > yield from g
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.871 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.871 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.871 alo = 473, ahi = 1101
2025-07-02 06:41:18.871 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.871 blo = 473, bhi = 1101
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.871 r"""
2025-07-02 06:41:18.872 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.872 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.872 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.872 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.872
2025-07-02 06:41:18.872 Example:
2025-07-02 06:41:18.872
2025-07-02 06:41:18.872 >>> d = Differ()
2025-07-02 06:41:18.872 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.872 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.872 >>> print(''.join(results), end="")
2025-07-02 06:41:18.872 - abcDefghiJkl
2025-07-02 06:41:18.872 + abcdefGhijkl
2025-07-02 06:41:18.872 """
2025-07-02 06:41:18.872
2025-07-02 06:41:18.872 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.872 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.872 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.873 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.873 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.873
2025-07-02 06:41:18.873 # search for the pair that matches best without being identical
2025-07-02 06:41:18.873 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.873 # on junk -- unless we have to)
2025-07-02 06:41:18.873 for j in range(blo, bhi):
2025-07-02 06:41:18.873 bj = b[j]
2025-07-02 06:41:18.873 cruncher.set_seq2(bj)
2025-07-02 06:41:18.873 for i in range(alo, ahi):
2025-07-02 06:41:18.873 ai = a[i]
2025-07-02 06:41:18.873 if ai == bj:
2025-07-02 06:41:18.873 if eqi is None:
2025-07-02 06:41:18.873 eqi, eqj = i, j
2025-07-02 06:41:18.873 continue
2025-07-02 06:41:18.873 cruncher.set_seq1(ai)
2025-07-02 06:41:18.873 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.873 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.873 # compares by a factor of 3.
2025-07-02 06:41:18.873 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.874 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.874 # of the computation is cached by cruncher
2025-07-02 06:41:18.874 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.874 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.874 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.874 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.874 if best_ratio < cutoff:
2025-07-02 06:41:18.874 # no non-identical "pretty close" pair
2025-07-02 06:41:18.874 if eqi is None:
2025-07-02 06:41:18.874 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.874 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.874 return
2025-07-02 06:41:18.874 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.874 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.874 else:
2025-07-02 06:41:18.874 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.874 eqi = None
2025-07-02 06:41:18.874
2025-07-02 06:41:18.874 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.874 # identical
2025-07-02 06:41:18.875
2025-07-02 06:41:18.875 # pump out diffs from before the synch point
2025-07-02 06:41:18.875 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.875
2025-07-02 06:41:18.875 # do intraline marking on the synch pair
2025-07-02 06:41:18.875 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.875 if eqi is None:
2025-07-02 06:41:18.875 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.875 atags = btags = ""
2025-07-02 06:41:18.875 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.875 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.875 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.875 if tag == 'replace':
2025-07-02 06:41:18.875 atags += '^' * la
2025-07-02 06:41:18.875 btags += '^' * lb
2025-07-02 06:41:18.875 elif tag == 'delete':
2025-07-02 06:41:18.875 atags += '-' * la
2025-07-02 06:41:18.875 elif tag == 'insert':
2025-07-02 06:41:18.875 btags += '+' * lb
2025-07-02 06:41:18.875 elif tag == 'equal':
2025-07-02 06:41:18.876 atags += ' ' * la
2025-07-02 06:41:18.876 btags += ' ' * lb
2025-07-02 06:41:18.876 else:
2025-07-02 06:41:18.876 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.876 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.876 else:
2025-07-02 06:41:18.876 # the synch pair is identical
2025-07-02 06:41:18.876 yield ' ' + aelt
2025-07-02 06:41:18.876
2025-07-02 06:41:18.876 # pump out diffs from after the synch point
2025-07-02 06:41:18.876 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.876
2025-07-02 06:41:18.876 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.876 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.876
2025-07-02 06:41:18.876 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.876 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.876 alo = 474, ahi = 1101
2025-07-02 06:41:18.877 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.877 blo = 474, bhi = 1101
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.877 g = []
2025-07-02 06:41:18.877 if alo < ahi:
2025-07-02 06:41:18.877 if blo < bhi:
2025-07-02 06:41:18.877 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.877 else:
2025-07-02 06:41:18.877 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.877 elif blo < bhi:
2025-07-02 06:41:18.877 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 > yield from g
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.877 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.878 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.878 alo = 474, ahi = 1101
2025-07-02 06:41:18.878 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.878 blo = 474, bhi = 1101
2025-07-02 06:41:18.878
2025-07-02 06:41:18.878 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.878 r"""
2025-07-02 06:41:18.878 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.878 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.878 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.878 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.878
2025-07-02 06:41:18.878 Example:
2025-07-02 06:41:18.878
2025-07-02 06:41:18.878 >>> d = Differ()
2025-07-02 06:41:18.878 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.878 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.878 >>> print(''.join(results), end="")
2025-07-02 06:41:18.878 - abcDefghiJkl
2025-07-02 06:41:18.879 + abcdefGhijkl
2025-07-02 06:41:18.879 """
2025-07-02 06:41:18.879
2025-07-02 06:41:18.879 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.879 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.879 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.879 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.879 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.879
2025-07-02 06:41:18.879 # search for the pair that matches best without being identical
2025-07-02 06:41:18.879 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.879 # on junk -- unless we have to)
2025-07-02 06:41:18.879 for j in range(blo, bhi):
2025-07-02 06:41:18.879 bj = b[j]
2025-07-02 06:41:18.879 cruncher.set_seq2(bj)
2025-07-02 06:41:18.879 for i in range(alo, ahi):
2025-07-02 06:41:18.879 ai = a[i]
2025-07-02 06:41:18.879 if ai == bj:
2025-07-02 06:41:18.880 if eqi is None:
2025-07-02 06:41:18.880 eqi, eqj = i, j
2025-07-02 06:41:18.880 continue
2025-07-02 06:41:18.880 cruncher.set_seq1(ai)
2025-07-02 06:41:18.880 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.880 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.880 # compares by a factor of 3.
2025-07-02 06:41:18.880 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.880 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.880 # of the computation is cached by cruncher
2025-07-02 06:41:18.880 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.880 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.880 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.880 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.880 if best_ratio < cutoff:
2025-07-02 06:41:18.880 # no non-identical "pretty close" pair
2025-07-02 06:41:18.880 if eqi is None:
2025-07-02 06:41:18.880 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.880 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.881 return
2025-07-02 06:41:18.881 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.881 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.881 else:
2025-07-02 06:41:18.881 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.881 eqi = None
2025-07-02 06:41:18.881
2025-07-02 06:41:18.881 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.881 # identical
2025-07-02 06:41:18.881
2025-07-02 06:41:18.881 # pump out diffs from before the synch point
2025-07-02 06:41:18.881 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.881
2025-07-02 06:41:18.881 # do intraline marking on the synch pair
2025-07-02 06:41:18.881 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.881 if eqi is None:
2025-07-02 06:41:18.881 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.881 atags = btags = ""
2025-07-02 06:41:18.881 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.881 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.881 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.882 if tag == 'replace':
2025-07-02 06:41:18.882 atags += '^' * la
2025-07-02 06:41:18.882 btags += '^' * lb
2025-07-02 06:41:18.882 elif tag == 'delete':
2025-07-02 06:41:18.882 atags += '-' * la
2025-07-02 06:41:18.882 elif tag == 'insert':
2025-07-02 06:41:18.882 btags += '+' * lb
2025-07-02 06:41:18.882 elif tag == 'equal':
2025-07-02 06:41:18.882 atags += ' ' * la
2025-07-02 06:41:18.882 btags += ' ' * lb
2025-07-02 06:41:18.882 else:
2025-07-02 06:41:18.882 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.882 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.882 else:
2025-07-02 06:41:18.882 # the synch pair is identical
2025-07-02 06:41:18.882 yield ' ' + aelt
2025-07-02 06:41:18.882
2025-07-02 06:41:18.882 # pump out diffs from after the synch point
2025-07-02 06:41:18.882 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.882
2025-07-02 06:41:18.883 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.883 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.883
2025-07-02 06:41:18.883 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.883 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.883 alo = 475, ahi = 1101
2025-07-02 06:41:18.883 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.883 blo = 475, bhi = 1101
2025-07-02 06:41:18.883
2025-07-02 06:41:18.883 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.883 g = []
2025-07-02 06:41:18.883 if alo < ahi:
2025-07-02 06:41:18.883 if blo < bhi:
2025-07-02 06:41:18.883 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.883 else:
2025-07-02 06:41:18.883 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.883 elif blo < bhi:
2025-07-02 06:41:18.883 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.883
2025-07-02 06:41:18.883 > yield from g
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.884 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.884 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.884 alo = 475, ahi = 1101
2025-07-02 06:41:18.884 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.884 blo = 475, bhi = 1101
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.884 r"""
2025-07-02 06:41:18.884 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.884 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.884 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.884 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884 Example:
2025-07-02 06:41:18.885
2025-07-02 06:41:18.885 >>> d = Differ()
2025-07-02 06:41:18.885 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.885 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.885 >>> print(''.join(results), end="")
2025-07-02 06:41:18.885 - abcDefghiJkl
2025-07-02 06:41:18.885 + abcdefGhijkl
2025-07-02 06:41:18.885 """
2025-07-02 06:41:18.885
2025-07-02 06:41:18.885 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.885 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.885 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.885 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.885 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.885
2025-07-02 06:41:18.885 # search for the pair that matches best without being identical
2025-07-02 06:41:18.885 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.886 # on junk -- unless we have to)
2025-07-02 06:41:18.886 for j in range(blo, bhi):
2025-07-02 06:41:18.886 bj = b[j]
2025-07-02 06:41:18.886 cruncher.set_seq2(bj)
2025-07-02 06:41:18.886 for i in range(alo, ahi):
2025-07-02 06:41:18.886 ai = a[i]
2025-07-02 06:41:18.886 if ai == bj:
2025-07-02 06:41:18.886 if eqi is None:
2025-07-02 06:41:18.886 eqi, eqj = i, j
2025-07-02 06:41:18.886 continue
2025-07-02 06:41:18.886 cruncher.set_seq1(ai)
2025-07-02 06:41:18.886 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.886 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.886 # compares by a factor of 3.
2025-07-02 06:41:18.886 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.886 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.886 # of the computation is cached by cruncher
2025-07-02 06:41:18.886 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.886 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.887 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.887 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.887 if best_ratio < cutoff:
2025-07-02 06:41:18.887 # no non-identical "pretty close" pair
2025-07-02 06:41:18.887 if eqi is None:
2025-07-02 06:41:18.887 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.887 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.887 return
2025-07-02 06:41:18.887 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.887 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.887 else:
2025-07-02 06:41:18.887 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.887 eqi = None
2025-07-02 06:41:18.887
2025-07-02 06:41:18.887 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.887 # identical
2025-07-02 06:41:18.887
2025-07-02 06:41:18.887 # pump out diffs from before the synch point
2025-07-02 06:41:18.887 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.887
2025-07-02 06:41:18.888 # do intraline marking on the synch pair
2025-07-02 06:41:18.888 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.888 if eqi is None:
2025-07-02 06:41:18.888 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.888 atags = btags = ""
2025-07-02 06:41:18.888 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.888 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.888 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.888 if tag == 'replace':
2025-07-02 06:41:18.888 atags += '^' * la
2025-07-02 06:41:18.888 btags += '^' * lb
2025-07-02 06:41:18.888 elif tag == 'delete':
2025-07-02 06:41:18.888 atags += '-' * la
2025-07-02 06:41:18.888 elif tag == 'insert':
2025-07-02 06:41:18.888 btags += '+' * lb
2025-07-02 06:41:18.888 elif tag == 'equal':
2025-07-02 06:41:18.888 atags += ' ' * la
2025-07-02 06:41:18.888 btags += ' ' * lb
2025-07-02 06:41:18.888 else:
2025-07-02 06:41:18.888 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.888 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.889 else:
2025-07-02 06:41:18.889 # the synch pair is identical
2025-07-02 06:41:18.889 yield ' ' + aelt
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889 # pump out diffs from after the synch point
2025-07-02 06:41:18.889 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.889 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.889 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.889 alo = 476, ahi = 1101
2025-07-02 06:41:18.889 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.889 blo = 476, bhi = 1101
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.889 g = []
2025-07-02 06:41:18.889 if alo < ahi:
2025-07-02 06:41:18.889 if blo < bhi:
2025-07-02 06:41:18.890 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.890 else:
2025-07-02 06:41:18.890 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.890 elif blo < bhi:
2025-07-02 06:41:18.890 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 > yield from g
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.890 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.890 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.890 alo = 476, ahi = 1101
2025-07-02 06:41:18.890 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.890 blo = 476, bhi = 1101
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.890 r"""
2025-07-02 06:41:18.890 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.891 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.891 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.891 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.891
2025-07-02 06:41:18.891 Example:
2025-07-02 06:41:18.891
2025-07-02 06:41:18.891 >>> d = Differ()
2025-07-02 06:41:18.891 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.891 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.891 >>> print(''.join(results), end="")
2025-07-02 06:41:18.891 - abcDefghiJkl
2025-07-02 06:41:18.891 + abcdefGhijkl
2025-07-02 06:41:18.891 """
2025-07-02 06:41:18.891
2025-07-02 06:41:18.891 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.891 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.891 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.891 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.892 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.892
2025-07-02 06:41:18.892 # search for the pair that matches best without being identical
2025-07-02 06:41:18.892 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.892 # on junk -- unless we have to)
2025-07-02 06:41:18.892 for j in range(blo, bhi):
2025-07-02 06:41:18.892 bj = b[j]
2025-07-02 06:41:18.892 cruncher.set_seq2(bj)
2025-07-02 06:41:18.892 for i in range(alo, ahi):
2025-07-02 06:41:18.892 ai = a[i]
2025-07-02 06:41:18.892 if ai == bj:
2025-07-02 06:41:18.892 if eqi is None:
2025-07-02 06:41:18.892 eqi, eqj = i, j
2025-07-02 06:41:18.892 continue
2025-07-02 06:41:18.892 cruncher.set_seq1(ai)
2025-07-02 06:41:18.892 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.892 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.892 # compares by a factor of 3.
2025-07-02 06:41:18.892 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.892 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.892 # of the computation is cached by cruncher
2025-07-02 06:41:18.893 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.893 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.893 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.893 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.893 if best_ratio < cutoff:
2025-07-02 06:41:18.893 # no non-identical "pretty close" pair
2025-07-02 06:41:18.893 if eqi is None:
2025-07-02 06:41:18.893 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.893 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.893 return
2025-07-02 06:41:18.893 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.893 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.893 else:
2025-07-02 06:41:18.893 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.893 eqi = None
2025-07-02 06:41:18.893
2025-07-02 06:41:18.893 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.894 # identical
2025-07-02 06:41:18.894
2025-07-02 06:41:18.894 # pump out diffs from before the synch point
2025-07-02 06:41:18.894 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.894
2025-07-02 06:41:18.894 # do intraline marking on the synch pair
2025-07-02 06:41:18.894 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.894 if eqi is None:
2025-07-02 06:41:18.894 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.894 atags = btags = ""
2025-07-02 06:41:18.894 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.894 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.894 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.894 if tag == 'replace':
2025-07-02 06:41:18.894 atags += '^' * la
2025-07-02 06:41:18.894 btags += '^' * lb
2025-07-02 06:41:18.894 elif tag == 'delete':
2025-07-02 06:41:18.894 atags += '-' * la
2025-07-02 06:41:18.894 elif tag == 'insert':
2025-07-02 06:41:18.894 btags += '+' * lb
2025-07-02 06:41:18.895 elif tag == 'equal':
2025-07-02 06:41:18.895 atags += ' ' * la
2025-07-02 06:41:18.895 btags += ' ' * lb
2025-07-02 06:41:18.895 else:
2025-07-02 06:41:18.895 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.895 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.895 else:
2025-07-02 06:41:18.895 # the synch pair is identical
2025-07-02 06:41:18.895 yield ' ' + aelt
2025-07-02 06:41:18.895
2025-07-02 06:41:18.895 # pump out diffs from after the synch point
2025-07-02 06:41:18.895 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.895
2025-07-02 06:41:18.895 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.895 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.895
2025-07-02 06:41:18.895 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.895 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.896 alo = 477, ahi = 1101
2025-07-02 06:41:18.896 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.896 blo = 477, bhi = 1101
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.896 g = []
2025-07-02 06:41:18.896 if alo < ahi:
2025-07-02 06:41:18.896 if blo < bhi:
2025-07-02 06:41:18.896 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.896 else:
2025-07-02 06:41:18.896 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.896 elif blo < bhi:
2025-07-02 06:41:18.896 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 > yield from g
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.896 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.897 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.897 alo = 477, ahi = 1101
2025-07-02 06:41:18.897 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.897 blo = 477, bhi = 1101
2025-07-02 06:41:18.897
2025-07-02 06:41:18.897 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.897 r"""
2025-07-02 06:41:18.897 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.897 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.897 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.897 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.897
2025-07-02 06:41:18.897 Example:
2025-07-02 06:41:18.897
2025-07-02 06:41:18.897 >>> d = Differ()
2025-07-02 06:41:18.897 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.897 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.897 >>> print(''.join(results), end="")
2025-07-02 06:41:18.897 - abcDefghiJkl
2025-07-02 06:41:18.898 + abcdefGhijkl
2025-07-02 06:41:18.898 """
2025-07-02 06:41:18.898
2025-07-02 06:41:18.898 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.898 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.898 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.898 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.898 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.898
2025-07-02 06:41:18.898 # search for the pair that matches best without being identical
2025-07-02 06:41:18.898 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.898 # on junk -- unless we have to)
2025-07-02 06:41:18.898 for j in range(blo, bhi):
2025-07-02 06:41:18.898 bj = b[j]
2025-07-02 06:41:18.898 cruncher.set_seq2(bj)
2025-07-02 06:41:18.898 for i in range(alo, ahi):
2025-07-02 06:41:18.898 ai = a[i]
2025-07-02 06:41:18.898 if ai == bj:
2025-07-02 06:41:18.898 if eqi is None:
2025-07-02 06:41:18.899 eqi, eqj = i, j
2025-07-02 06:41:18.899 continue
2025-07-02 06:41:18.899 cruncher.set_seq1(ai)
2025-07-02 06:41:18.899 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.899 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.899 # compares by a factor of 3.
2025-07-02 06:41:18.899 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.899 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.899 # of the computation is cached by cruncher
2025-07-02 06:41:18.899 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.899 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.899 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.899 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.899 if best_ratio < cutoff:
2025-07-02 06:41:18.899 # no non-identical "pretty close" pair
2025-07-02 06:41:18.899 if eqi is None:
2025-07-02 06:41:18.899 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.899 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.899 return
2025-07-02 06:41:18.900 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.900 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.900 else:
2025-07-02 06:41:18.900 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.900 eqi = None
2025-07-02 06:41:18.900
2025-07-02 06:41:18.900 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.900 # identical
2025-07-02 06:41:18.900
2025-07-02 06:41:18.900 # pump out diffs from before the synch point
2025-07-02 06:41:18.900 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.900
2025-07-02 06:41:18.900 # do intraline marking on the synch pair
2025-07-02 06:41:18.900 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.900 if eqi is None:
2025-07-02 06:41:18.900 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.900 atags = btags = ""
2025-07-02 06:41:18.900 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.900 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.900 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.900 if tag == 'replace':
2025-07-02 06:41:18.901 atags += '^' * la
2025-07-02 06:41:18.901 btags += '^' * lb
2025-07-02 06:41:18.901 elif tag == 'delete':
2025-07-02 06:41:18.901 atags += '-' * la
2025-07-02 06:41:18.901 elif tag == 'insert':
2025-07-02 06:41:18.901 btags += '+' * lb
2025-07-02 06:41:18.901 elif tag == 'equal':
2025-07-02 06:41:18.901 atags += ' ' * la
2025-07-02 06:41:18.901 btags += ' ' * lb
2025-07-02 06:41:18.901 else:
2025-07-02 06:41:18.901 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.901 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.901 else:
2025-07-02 06:41:18.901 # the synch pair is identical
2025-07-02 06:41:18.901 yield ' ' + aelt
2025-07-02 06:41:18.901
2025-07-02 06:41:18.901 # pump out diffs from after the synch point
2025-07-02 06:41:18.901 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.901
2025-07-02 06:41:18.901 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.902 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.902
2025-07-02 06:41:18.902 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.902 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.902 alo = 478, ahi = 1101
2025-07-02 06:41:18.902 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.902 blo = 478, bhi = 1101
2025-07-02 06:41:18.902
2025-07-02 06:41:18.902 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.902 g = []
2025-07-02 06:41:18.902 if alo < ahi:
2025-07-02 06:41:18.902 if blo < bhi:
2025-07-02 06:41:18.902 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.902 else:
2025-07-02 06:41:18.902 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.902 elif blo < bhi:
2025-07-02 06:41:18.902 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.902
2025-07-02 06:41:18.902 > yield from g
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.903 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.903 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.903 alo = 478, ahi = 1101
2025-07-02 06:41:18.903 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.903 blo = 478, bhi = 1101
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.903 r"""
2025-07-02 06:41:18.903 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.903 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.903 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.903 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903 Example:
2025-07-02 06:41:18.903
2025-07-02 06:41:18.904 >>> d = Differ()
2025-07-02 06:41:18.904 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.904 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.904 >>> print(''.join(results), end="")
2025-07-02 06:41:18.904 - abcDefghiJkl
2025-07-02 06:41:18.904 + abcdefGhijkl
2025-07-02 06:41:18.904 """
2025-07-02 06:41:18.904
2025-07-02 06:41:18.904 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.904 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.904 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.904 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.904 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.904
2025-07-02 06:41:18.904 # search for the pair that matches best without being identical
2025-07-02 06:41:18.904 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.904 # on junk -- unless we have to)
2025-07-02 06:41:18.905 for j in range(blo, bhi):
2025-07-02 06:41:18.905 bj = b[j]
2025-07-02 06:41:18.905 cruncher.set_seq2(bj)
2025-07-02 06:41:18.905 for i in range(alo, ahi):
2025-07-02 06:41:18.905 ai = a[i]
2025-07-02 06:41:18.905 if ai == bj:
2025-07-02 06:41:18.905 if eqi is None:
2025-07-02 06:41:18.905 eqi, eqj = i, j
2025-07-02 06:41:18.905 continue
2025-07-02 06:41:18.905 cruncher.set_seq1(ai)
2025-07-02 06:41:18.905 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.905 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.905 # compares by a factor of 3.
2025-07-02 06:41:18.905 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.905 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.905 # of the computation is cached by cruncher
2025-07-02 06:41:18.905 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.905 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.905 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.906 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.906 if best_ratio < cutoff:
2025-07-02 06:41:18.906 # no non-identical "pretty close" pair
2025-07-02 06:41:18.906 if eqi is None:
2025-07-02 06:41:18.906 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.906 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.906 return
2025-07-02 06:41:18.906 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.906 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.906 else:
2025-07-02 06:41:18.906 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.906 eqi = None
2025-07-02 06:41:18.906
2025-07-02 06:41:18.906 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.906 # identical
2025-07-02 06:41:18.906
2025-07-02 06:41:18.906 # pump out diffs from before the synch point
2025-07-02 06:41:18.906 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.906
2025-07-02 06:41:18.906 # do intraline marking on the synch pair
2025-07-02 06:41:18.907 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.907 if eqi is None:
2025-07-02 06:41:18.907 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.907 atags = btags = ""
2025-07-02 06:41:18.907 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.907 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.907 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.907 if tag == 'replace':
2025-07-02 06:41:18.907 atags += '^' * la
2025-07-02 06:41:18.907 btags += '^' * lb
2025-07-02 06:41:18.907 elif tag == 'delete':
2025-07-02 06:41:18.907 atags += '-' * la
2025-07-02 06:41:18.907 elif tag == 'insert':
2025-07-02 06:41:18.907 btags += '+' * lb
2025-07-02 06:41:18.907 elif tag == 'equal':
2025-07-02 06:41:18.907 atags += ' ' * la
2025-07-02 06:41:18.907 btags += ' ' * lb
2025-07-02 06:41:18.907 else:
2025-07-02 06:41:18.907 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.907 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.908 else:
2025-07-02 06:41:18.908 # the synch pair is identical
2025-07-02 06:41:18.908 yield ' ' + aelt
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908 # pump out diffs from after the synch point
2025-07-02 06:41:18.908 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.908 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.908 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.908 alo = 479, ahi = 1101
2025-07-02 06:41:18.908 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.908 blo = 479, bhi = 1101
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.908 g = []
2025-07-02 06:41:18.908 if alo < ahi:
2025-07-02 06:41:18.908 if blo < bhi:
2025-07-02 06:41:18.909 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.909 else:
2025-07-02 06:41:18.909 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.909 elif blo < bhi:
2025-07-02 06:41:18.909 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 > yield from g
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.909 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.909 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.909 alo = 479, ahi = 1101
2025-07-02 06:41:18.909 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.909 blo = 479, bhi = 1101
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.909 r"""
2025-07-02 06:41:18.909 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.910 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.910 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.910 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.910
2025-07-02 06:41:18.910 Example:
2025-07-02 06:41:18.910
2025-07-02 06:41:18.910 >>> d = Differ()
2025-07-02 06:41:18.910 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.910 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.910 >>> print(''.join(results), end="")
2025-07-02 06:41:18.910 - abcDefghiJkl
2025-07-02 06:41:18.910 + abcdefGhijkl
2025-07-02 06:41:18.910 """
2025-07-02 06:41:18.910
2025-07-02 06:41:18.910 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.910 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.910 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.910 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.911 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.911
2025-07-02 06:41:18.911 # search for the pair that matches best without being identical
2025-07-02 06:41:18.911 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.911 # on junk -- unless we have to)
2025-07-02 06:41:18.911 for j in range(blo, bhi):
2025-07-02 06:41:18.911 bj = b[j]
2025-07-02 06:41:18.911 cruncher.set_seq2(bj)
2025-07-02 06:41:18.911 for i in range(alo, ahi):
2025-07-02 06:41:18.911 ai = a[i]
2025-07-02 06:41:18.911 if ai == bj:
2025-07-02 06:41:18.911 if eqi is None:
2025-07-02 06:41:18.911 eqi, eqj = i, j
2025-07-02 06:41:18.911 continue
2025-07-02 06:41:18.911 cruncher.set_seq1(ai)
2025-07-02 06:41:18.911 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.911 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.911 # compares by a factor of 3.
2025-07-02 06:41:18.912 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.912 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.912 # of the computation is cached by cruncher
2025-07-02 06:41:18.912 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.912 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.912 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.912 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.912 if best_ratio < cutoff:
2025-07-02 06:41:18.912 # no non-identical "pretty close" pair
2025-07-02 06:41:18.912 if eqi is None:
2025-07-02 06:41:18.912 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.912 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.912 return
2025-07-02 06:41:18.912 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.912 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.912 else:
2025-07-02 06:41:18.912 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.912 eqi = None
2025-07-02 06:41:18.912
2025-07-02 06:41:18.913 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.913 # identical
2025-07-02 06:41:18.913
2025-07-02 06:41:18.913 # pump out diffs from before the synch point
2025-07-02 06:41:18.913 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.913
2025-07-02 06:41:18.913 # do intraline marking on the synch pair
2025-07-02 06:41:18.913 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.913 if eqi is None:
2025-07-02 06:41:18.913 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.913 atags = btags = ""
2025-07-02 06:41:18.913 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.913 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.913 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.913 if tag == 'replace':
2025-07-02 06:41:18.913 atags += '^' * la
2025-07-02 06:41:18.913 btags += '^' * lb
2025-07-02 06:41:18.913 elif tag == 'delete':
2025-07-02 06:41:18.913 atags += '-' * la
2025-07-02 06:41:18.913 elif tag == 'insert':
2025-07-02 06:41:18.914 btags += '+' * lb
2025-07-02 06:41:18.914 elif tag == 'equal':
2025-07-02 06:41:18.914 atags += ' ' * la
2025-07-02 06:41:18.914 btags += ' ' * lb
2025-07-02 06:41:18.914 else:
2025-07-02 06:41:18.914 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.914 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.914 else:
2025-07-02 06:41:18.914 # the synch pair is identical
2025-07-02 06:41:18.914 yield ' ' + aelt
2025-07-02 06:41:18.914
2025-07-02 06:41:18.914 # pump out diffs from after the synch point
2025-07-02 06:41:18.914 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.914
2025-07-02 06:41:18.914 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.914 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.914
2025-07-02 06:41:18.914 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.914 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.914 alo = 480, ahi = 1101
2025-07-02 06:41:18.915 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.915 blo = 480, bhi = 1101
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.915 g = []
2025-07-02 06:41:18.915 if alo < ahi:
2025-07-02 06:41:18.915 if blo < bhi:
2025-07-02 06:41:18.915 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.915 else:
2025-07-02 06:41:18.915 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.915 elif blo < bhi:
2025-07-02 06:41:18.915 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 > yield from g
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.915 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.915 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.916 alo = 480, ahi = 1101
2025-07-02 06:41:18.916 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.916 blo = 480, bhi = 1101
2025-07-02 06:41:18.916
2025-07-02 06:41:18.916 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.916 r"""
2025-07-02 06:41:18.916 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.916 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.916 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.916 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.916
2025-07-02 06:41:18.916 Example:
2025-07-02 06:41:18.916
2025-07-02 06:41:18.916 >>> d = Differ()
2025-07-02 06:41:18.916 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.916 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.916 >>> print(''.join(results), end="")
2025-07-02 06:41:18.916 - abcDefghiJkl
2025-07-02 06:41:18.916 + abcdefGhijkl
2025-07-02 06:41:18.917 """
2025-07-02 06:41:18.917
2025-07-02 06:41:18.917 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.917 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.917 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.917 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.917 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.917
2025-07-02 06:41:18.917 # search for the pair that matches best without being identical
2025-07-02 06:41:18.917 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.917 # on junk -- unless we have to)
2025-07-02 06:41:18.917 for j in range(blo, bhi):
2025-07-02 06:41:18.917 bj = b[j]
2025-07-02 06:41:18.917 cruncher.set_seq2(bj)
2025-07-02 06:41:18.917 for i in range(alo, ahi):
2025-07-02 06:41:18.917 ai = a[i]
2025-07-02 06:41:18.917 if ai == bj:
2025-07-02 06:41:18.917 if eqi is None:
2025-07-02 06:41:18.917 eqi, eqj = i, j
2025-07-02 06:41:18.917 continue
2025-07-02 06:41:18.918 cruncher.set_seq1(ai)
2025-07-02 06:41:18.918 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.918 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.918 # compares by a factor of 3.
2025-07-02 06:41:18.918 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.918 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.918 # of the computation is cached by cruncher
2025-07-02 06:41:18.918 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.918 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.918 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.918 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.918 if best_ratio < cutoff:
2025-07-02 06:41:18.918 # no non-identical "pretty close" pair
2025-07-02 06:41:18.918 if eqi is None:
2025-07-02 06:41:18.918 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.918 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.918 return
2025-07-02 06:41:18.918 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.918 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.918 else:
2025-07-02 06:41:18.919 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.919 eqi = None
2025-07-02 06:41:18.919
2025-07-02 06:41:18.919 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.919 # identical
2025-07-02 06:41:18.919
2025-07-02 06:41:18.919 # pump out diffs from before the synch point
2025-07-02 06:41:18.919 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.919
2025-07-02 06:41:18.919 # do intraline marking on the synch pair
2025-07-02 06:41:18.919 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.919 if eqi is None:
2025-07-02 06:41:18.919 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.919 atags = btags = ""
2025-07-02 06:41:18.919 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.919 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.919 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.919 if tag == 'replace':
2025-07-02 06:41:18.919 atags += '^' * la
2025-07-02 06:41:18.920 btags += '^' * lb
2025-07-02 06:41:18.920 elif tag == 'delete':
2025-07-02 06:41:18.920 atags += '-' * la
2025-07-02 06:41:18.920 elif tag == 'insert':
2025-07-02 06:41:18.920 btags += '+' * lb
2025-07-02 06:41:18.920 elif tag == 'equal':
2025-07-02 06:41:18.920 atags += ' ' * la
2025-07-02 06:41:18.920 btags += ' ' * lb
2025-07-02 06:41:18.920 else:
2025-07-02 06:41:18.920 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.920 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.920 else:
2025-07-02 06:41:18.920 # the synch pair is identical
2025-07-02 06:41:18.920 yield ' ' + aelt
2025-07-02 06:41:18.920
2025-07-02 06:41:18.920 # pump out diffs from after the synch point
2025-07-02 06:41:18.920 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.920
2025-07-02 06:41:18.920 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.921 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.921
2025-07-02 06:41:18.921 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.921 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.921 alo = 481, ahi = 1101
2025-07-02 06:41:18.921 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.921 blo = 481, bhi = 1101
2025-07-02 06:41:18.921
2025-07-02 06:41:18.921 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.921 g = []
2025-07-02 06:41:18.921 if alo < ahi:
2025-07-02 06:41:18.921 if blo < bhi:
2025-07-02 06:41:18.921 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.921 else:
2025-07-02 06:41:18.921 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.921 elif blo < bhi:
2025-07-02 06:41:18.921 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.921
2025-07-02 06:41:18.921 > yield from g
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.922 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.922 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.922 alo = 481, ahi = 1101
2025-07-02 06:41:18.922 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.922 blo = 481, bhi = 1101
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.922 r"""
2025-07-02 06:41:18.922 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.922 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.922 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.922 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 Example:
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 >>> d = Differ()
2025-07-02 06:41:18.923 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.923 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.923 >>> print(''.join(results), end="")
2025-07-02 06:41:18.923 - abcDefghiJkl
2025-07-02 06:41:18.923 + abcdefGhijkl
2025-07-02 06:41:18.923 """
2025-07-02 06:41:18.923
2025-07-02 06:41:18.923 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.923 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.923 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.923 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.923 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.923
2025-07-02 06:41:18.923 # search for the pair that matches best without being identical
2025-07-02 06:41:18.923 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.923 # on junk -- unless we have to)
2025-07-02 06:41:18.923 for j in range(blo, bhi):
2025-07-02 06:41:18.923 bj = b[j]
2025-07-02 06:41:18.924 cruncher.set_seq2(bj)
2025-07-02 06:41:18.924 for i in range(alo, ahi):
2025-07-02 06:41:18.924 ai = a[i]
2025-07-02 06:41:18.924 if ai == bj:
2025-07-02 06:41:18.924 if eqi is None:
2025-07-02 06:41:18.924 eqi, eqj = i, j
2025-07-02 06:41:18.924 continue
2025-07-02 06:41:18.924 cruncher.set_seq1(ai)
2025-07-02 06:41:18.924 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.924 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.924 # compares by a factor of 3.
2025-07-02 06:41:18.924 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.924 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.924 # of the computation is cached by cruncher
2025-07-02 06:41:18.924 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.924 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.924 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.924 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.924 if best_ratio < cutoff:
2025-07-02 06:41:18.924 # no non-identical "pretty close" pair
2025-07-02 06:41:18.925 if eqi is None:
2025-07-02 06:41:18.925 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.925 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.925 return
2025-07-02 06:41:18.925 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.925 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.925 else:
2025-07-02 06:41:18.925 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.925 eqi = None
2025-07-02 06:41:18.925
2025-07-02 06:41:18.925 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.925 # identical
2025-07-02 06:41:18.925
2025-07-02 06:41:18.925 # pump out diffs from before the synch point
2025-07-02 06:41:18.925 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.925
2025-07-02 06:41:18.925 # do intraline marking on the synch pair
2025-07-02 06:41:18.925 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.925 if eqi is None:
2025-07-02 06:41:18.925 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.926 atags = btags = ""
2025-07-02 06:41:18.926 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.926 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.926 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.926 if tag == 'replace':
2025-07-02 06:41:18.926 atags += '^' * la
2025-07-02 06:41:18.926 btags += '^' * lb
2025-07-02 06:41:18.926 elif tag == 'delete':
2025-07-02 06:41:18.926 atags += '-' * la
2025-07-02 06:41:18.926 elif tag == 'insert':
2025-07-02 06:41:18.926 btags += '+' * lb
2025-07-02 06:41:18.926 elif tag == 'equal':
2025-07-02 06:41:18.926 atags += ' ' * la
2025-07-02 06:41:18.926 btags += ' ' * lb
2025-07-02 06:41:18.926 else:
2025-07-02 06:41:18.926 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.926 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.926 else:
2025-07-02 06:41:18.926 # the synch pair is identical
2025-07-02 06:41:18.926 yield ' ' + aelt
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927 # pump out diffs from after the synch point
2025-07-02 06:41:18.927 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.927 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.927 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.927 alo = 482, ahi = 1101
2025-07-02 06:41:18.927 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.927 blo = 482, bhi = 1101
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.927 g = []
2025-07-02 06:41:18.927 if alo < ahi:
2025-07-02 06:41:18.927 if blo < bhi:
2025-07-02 06:41:18.927 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.928 else:
2025-07-02 06:41:18.928 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.928 elif blo < bhi:
2025-07-02 06:41:18.928 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 > yield from g
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.928 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.928 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.928 alo = 482, ahi = 1101
2025-07-02 06:41:18.928 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.928 blo = 482, bhi = 1101
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.928 r"""
2025-07-02 06:41:18.929 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.929 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.929 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.929 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.929
2025-07-02 06:41:18.929 Example:
2025-07-02 06:41:18.929
2025-07-02 06:41:18.929 >>> d = Differ()
2025-07-02 06:41:18.929 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.929 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.929 >>> print(''.join(results), end="")
2025-07-02 06:41:18.929 - abcDefghiJkl
2025-07-02 06:41:18.929 + abcdefGhijkl
2025-07-02 06:41:18.929 """
2025-07-02 06:41:18.929
2025-07-02 06:41:18.929 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.929 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.930 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.930 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.930 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.930
2025-07-02 06:41:18.930 # search for the pair that matches best without being identical
2025-07-02 06:41:18.930 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.930 # on junk -- unless we have to)
2025-07-02 06:41:18.930 for j in range(blo, bhi):
2025-07-02 06:41:18.930 bj = b[j]
2025-07-02 06:41:18.930 cruncher.set_seq2(bj)
2025-07-02 06:41:18.930 for i in range(alo, ahi):
2025-07-02 06:41:18.930 ai = a[i]
2025-07-02 06:41:18.930 if ai == bj:
2025-07-02 06:41:18.930 if eqi is None:
2025-07-02 06:41:18.930 eqi, eqj = i, j
2025-07-02 06:41:18.930 continue
2025-07-02 06:41:18.930 cruncher.set_seq1(ai)
2025-07-02 06:41:18.930 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.930 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.930 # compares by a factor of 3.
2025-07-02 06:41:18.931 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.931 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.931 # of the computation is cached by cruncher
2025-07-02 06:41:18.931 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.931 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.931 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.931 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.931 if best_ratio < cutoff:
2025-07-02 06:41:18.931 # no non-identical "pretty close" pair
2025-07-02 06:41:18.931 if eqi is None:
2025-07-02 06:41:18.931 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.931 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.931 return
2025-07-02 06:41:18.931 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.931 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.931 else:
2025-07-02 06:41:18.931 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.931 eqi = None
2025-07-02 06:41:18.931
2025-07-02 06:41:18.931 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.932 # identical
2025-07-02 06:41:18.932
2025-07-02 06:41:18.932 # pump out diffs from before the synch point
2025-07-02 06:41:18.932 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.932
2025-07-02 06:41:18.932 # do intraline marking on the synch pair
2025-07-02 06:41:18.932 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.932 if eqi is None:
2025-07-02 06:41:18.932 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.932 atags = btags = ""
2025-07-02 06:41:18.932 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.932 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.932 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.932 if tag == 'replace':
2025-07-02 06:41:18.932 atags += '^' * la
2025-07-02 06:41:18.932 btags += '^' * lb
2025-07-02 06:41:18.932 elif tag == 'delete':
2025-07-02 06:41:18.932 atags += '-' * la
2025-07-02 06:41:18.932 elif tag == 'insert':
2025-07-02 06:41:18.932 btags += '+' * lb
2025-07-02 06:41:18.932 elif tag == 'equal':
2025-07-02 06:41:18.933 atags += ' ' * la
2025-07-02 06:41:18.933 btags += ' ' * lb
2025-07-02 06:41:18.933 else:
2025-07-02 06:41:18.933 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.933 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.933 else:
2025-07-02 06:41:18.933 # the synch pair is identical
2025-07-02 06:41:18.933 yield ' ' + aelt
2025-07-02 06:41:18.933
2025-07-02 06:41:18.933 # pump out diffs from after the synch point
2025-07-02 06:41:18.933 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.933
2025-07-02 06:41:18.933 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.933 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.933
2025-07-02 06:41:18.933 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.933 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.933 alo = 483, ahi = 1101
2025-07-02 06:41:18.933 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.933 blo = 483, bhi = 1101
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.934 g = []
2025-07-02 06:41:18.934 if alo < ahi:
2025-07-02 06:41:18.934 if blo < bhi:
2025-07-02 06:41:18.934 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.934 else:
2025-07-02 06:41:18.934 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.934 elif blo < bhi:
2025-07-02 06:41:18.934 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 > yield from g
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.934 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.934 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.934 alo = 483, ahi = 1101
2025-07-02 06:41:18.934 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.935 blo = 483, bhi = 1101
2025-07-02 06:41:18.935
2025-07-02 06:41:18.935 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.935 r"""
2025-07-02 06:41:18.935 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.935 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.935 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.935 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.935
2025-07-02 06:41:18.935 Example:
2025-07-02 06:41:18.935
2025-07-02 06:41:18.935 >>> d = Differ()
2025-07-02 06:41:18.935 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.935 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.935 >>> print(''.join(results), end="")
2025-07-02 06:41:18.935 - abcDefghiJkl
2025-07-02 06:41:18.935 + abcdefGhijkl
2025-07-02 06:41:18.935 """
2025-07-02 06:41:18.936
2025-07-02 06:41:18.936 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.936 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.936 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.936 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.936 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.936
2025-07-02 06:41:18.936 # search for the pair that matches best without being identical
2025-07-02 06:41:18.936 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.936 # on junk -- unless we have to)
2025-07-02 06:41:18.936 for j in range(blo, bhi):
2025-07-02 06:41:18.936 bj = b[j]
2025-07-02 06:41:18.936 cruncher.set_seq2(bj)
2025-07-02 06:41:18.936 for i in range(alo, ahi):
2025-07-02 06:41:18.936 ai = a[i]
2025-07-02 06:41:18.936 if ai == bj:
2025-07-02 06:41:18.936 if eqi is None:
2025-07-02 06:41:18.936 eqi, eqj = i, j
2025-07-02 06:41:18.936 continue
2025-07-02 06:41:18.936 cruncher.set_seq1(ai)
2025-07-02 06:41:18.937 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.937 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.937 # compares by a factor of 3.
2025-07-02 06:41:18.937 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.937 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.937 # of the computation is cached by cruncher
2025-07-02 06:41:18.937 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.937 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.937 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.937 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.937 if best_ratio < cutoff:
2025-07-02 06:41:18.937 # no non-identical "pretty close" pair
2025-07-02 06:41:18.937 if eqi is None:
2025-07-02 06:41:18.937 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.937 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.937 return
2025-07-02 06:41:18.937 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.937 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.938 else:
2025-07-02 06:41:18.938 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.938 eqi = None
2025-07-02 06:41:18.938
2025-07-02 06:41:18.938 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.938 # identical
2025-07-02 06:41:18.938
2025-07-02 06:41:18.938 # pump out diffs from before the synch point
2025-07-02 06:41:18.938 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.938
2025-07-02 06:41:18.938 # do intraline marking on the synch pair
2025-07-02 06:41:18.938 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.938 if eqi is None:
2025-07-02 06:41:18.938 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.938 atags = btags = ""
2025-07-02 06:41:18.938 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.938 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.938 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.938 if tag == 'replace':
2025-07-02 06:41:18.938 atags += '^' * la
2025-07-02 06:41:18.939 btags += '^' * lb
2025-07-02 06:41:18.939 elif tag == 'delete':
2025-07-02 06:41:18.939 atags += '-' * la
2025-07-02 06:41:18.939 elif tag == 'insert':
2025-07-02 06:41:18.939 btags += '+' * lb
2025-07-02 06:41:18.939 elif tag == 'equal':
2025-07-02 06:41:18.939 atags += ' ' * la
2025-07-02 06:41:18.939 btags += ' ' * lb
2025-07-02 06:41:18.939 else:
2025-07-02 06:41:18.939 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.939 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.939 else:
2025-07-02 06:41:18.939 # the synch pair is identical
2025-07-02 06:41:18.939 yield ' ' + aelt
2025-07-02 06:41:18.939
2025-07-02 06:41:18.939 # pump out diffs from after the synch point
2025-07-02 06:41:18.939 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.939
2025-07-02 06:41:18.939 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.939 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.940 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.940 alo = 484, ahi = 1101
2025-07-02 06:41:18.940 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.940 blo = 484, bhi = 1101
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.940 g = []
2025-07-02 06:41:18.940 if alo < ahi:
2025-07-02 06:41:18.940 if blo < bhi:
2025-07-02 06:41:18.940 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.940 else:
2025-07-02 06:41:18.940 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.940 elif blo < bhi:
2025-07-02 06:41:18.940 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 > yield from g
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.940 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.941 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.941 alo = 484, ahi = 1101
2025-07-02 06:41:18.941 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.941 blo = 484, bhi = 1101
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.941 r"""
2025-07-02 06:41:18.941 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.941 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.941 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.941 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941 Example:
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941 >>> d = Differ()
2025-07-02 06:41:18.941 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.941 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.941 >>> print(''.join(results), end="")
2025-07-02 06:41:18.942 - abcDefghiJkl
2025-07-02 06:41:18.942 + abcdefGhijkl
2025-07-02 06:41:18.942 """
2025-07-02 06:41:18.942
2025-07-02 06:41:18.942 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.942 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.942 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.942 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.942 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.942
2025-07-02 06:41:18.942 # search for the pair that matches best without being identical
2025-07-02 06:41:18.942 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.942 # on junk -- unless we have to)
2025-07-02 06:41:18.942 for j in range(blo, bhi):
2025-07-02 06:41:18.942 bj = b[j]
2025-07-02 06:41:18.942 cruncher.set_seq2(bj)
2025-07-02 06:41:18.943 for i in range(alo, ahi):
2025-07-02 06:41:18.943 ai = a[i]
2025-07-02 06:41:18.943 if ai == bj:
2025-07-02 06:41:18.943 if eqi is None:
2025-07-02 06:41:18.943 eqi, eqj = i, j
2025-07-02 06:41:18.943 continue
2025-07-02 06:41:18.943 cruncher.set_seq1(ai)
2025-07-02 06:41:18.943 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.943 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.943 # compares by a factor of 3.
2025-07-02 06:41:18.943 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.943 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.943 # of the computation is cached by cruncher
2025-07-02 06:41:18.943 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.943 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.943 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.943 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.943 if best_ratio < cutoff:
2025-07-02 06:41:18.943 # no non-identical "pretty close" pair
2025-07-02 06:41:18.943 if eqi is None:
2025-07-02 06:41:18.944 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.944 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.944 return
2025-07-02 06:41:18.944 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.944 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.944 else:
2025-07-02 06:41:18.944 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.944 eqi = None
2025-07-02 06:41:18.944
2025-07-02 06:41:18.944 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.944 # identical
2025-07-02 06:41:18.944
2025-07-02 06:41:18.944 # pump out diffs from before the synch point
2025-07-02 06:41:18.944 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.944
2025-07-02 06:41:18.944 # do intraline marking on the synch pair
2025-07-02 06:41:18.944 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.944 if eqi is None:
2025-07-02 06:41:18.944 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.944 atags = btags = ""
2025-07-02 06:41:18.945 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.945 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.945 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.945 if tag == 'replace':
2025-07-02 06:41:18.945 atags += '^' * la
2025-07-02 06:41:18.945 btags += '^' * lb
2025-07-02 06:41:18.945 elif tag == 'delete':
2025-07-02 06:41:18.945 atags += '-' * la
2025-07-02 06:41:18.945 elif tag == 'insert':
2025-07-02 06:41:18.945 btags += '+' * lb
2025-07-02 06:41:18.945 elif tag == 'equal':
2025-07-02 06:41:18.945 atags += ' ' * la
2025-07-02 06:41:18.945 btags += ' ' * lb
2025-07-02 06:41:18.945 else:
2025-07-02 06:41:18.945 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.945 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.945 else:
2025-07-02 06:41:18.945 # the synch pair is identical
2025-07-02 06:41:18.945 yield ' ' + aelt
2025-07-02 06:41:18.945
2025-07-02 06:41:18.946 # pump out diffs from after the synch point
2025-07-02 06:41:18.946 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.946
2025-07-02 06:41:18.946 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.946 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.946
2025-07-02 06:41:18.946 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.946 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.946 alo = 485, ahi = 1101
2025-07-02 06:41:18.946 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.946 blo = 485, bhi = 1101
2025-07-02 06:41:18.946
2025-07-02 06:41:18.946 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.946 g = []
2025-07-02 06:41:18.946 if alo < ahi:
2025-07-02 06:41:18.946 if blo < bhi:
2025-07-02 06:41:18.946 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.947 else:
2025-07-02 06:41:18.947 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.947 elif blo < bhi:
2025-07-02 06:41:18.947 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 > yield from g
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.947 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.947 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.947 alo = 485, ahi = 1101
2025-07-02 06:41:18.947 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.947 blo = 485, bhi = 1101
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.947 r"""
2025-07-02 06:41:18.947 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.948 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.948 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.948 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.948
2025-07-02 06:41:18.948 Example:
2025-07-02 06:41:18.948
2025-07-02 06:41:18.948 >>> d = Differ()
2025-07-02 06:41:18.948 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.948 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.948 >>> print(''.join(results), end="")
2025-07-02 06:41:18.948 - abcDefghiJkl
2025-07-02 06:41:18.948 + abcdefGhijkl
2025-07-02 06:41:18.948 """
2025-07-02 06:41:18.948
2025-07-02 06:41:18.948 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.948 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.948 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.948 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.949 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.949
2025-07-02 06:41:18.949 # search for the pair that matches best without being identical
2025-07-02 06:41:18.949 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.949 # on junk -- unless we have to)
2025-07-02 06:41:18.949 for j in range(blo, bhi):
2025-07-02 06:41:18.949 bj = b[j]
2025-07-02 06:41:18.949 cruncher.set_seq2(bj)
2025-07-02 06:41:18.949 for i in range(alo, ahi):
2025-07-02 06:41:18.949 ai = a[i]
2025-07-02 06:41:18.949 if ai == bj:
2025-07-02 06:41:18.949 if eqi is None:
2025-07-02 06:41:18.949 eqi, eqj = i, j
2025-07-02 06:41:18.949 continue
2025-07-02 06:41:18.949 cruncher.set_seq1(ai)
2025-07-02 06:41:18.949 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.949 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.949 # compares by a factor of 3.
2025-07-02 06:41:18.949 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.949 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.950 # of the computation is cached by cruncher
2025-07-02 06:41:18.950 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.950 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.950 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.950 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.950 if best_ratio < cutoff:
2025-07-02 06:41:18.950 # no non-identical "pretty close" pair
2025-07-02 06:41:18.950 if eqi is None:
2025-07-02 06:41:18.950 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.950 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.950 return
2025-07-02 06:41:18.950 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.950 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.950 else:
2025-07-02 06:41:18.950 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.950 eqi = None
2025-07-02 06:41:18.950
2025-07-02 06:41:18.950 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.950 # identical
2025-07-02 06:41:18.950
2025-07-02 06:41:18.950 # pump out diffs from before the synch point
2025-07-02 06:41:18.951 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.951
2025-07-02 06:41:18.951 # do intraline marking on the synch pair
2025-07-02 06:41:18.951 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.951 if eqi is None:
2025-07-02 06:41:18.951 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.951 atags = btags = ""
2025-07-02 06:41:18.951 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.951 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.951 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.951 if tag == 'replace':
2025-07-02 06:41:18.951 atags += '^' * la
2025-07-02 06:41:18.951 btags += '^' * lb
2025-07-02 06:41:18.951 elif tag == 'delete':
2025-07-02 06:41:18.951 atags += '-' * la
2025-07-02 06:41:18.951 elif tag == 'insert':
2025-07-02 06:41:18.951 btags += '+' * lb
2025-07-02 06:41:18.951 elif tag == 'equal':
2025-07-02 06:41:18.951 atags += ' ' * la
2025-07-02 06:41:18.951 btags += ' ' * lb
2025-07-02 06:41:18.952 else:
2025-07-02 06:41:18.952 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.952 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.952 else:
2025-07-02 06:41:18.952 # the synch pair is identical
2025-07-02 06:41:18.952 yield ' ' + aelt
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952 # pump out diffs from after the synch point
2025-07-02 06:41:18.952 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.952 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.952 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.952 alo = 488, ahi = 1101
2025-07-02 06:41:18.952 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.952 blo = 488, bhi = 1101
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.953 g = []
2025-07-02 06:41:18.953 if alo < ahi:
2025-07-02 06:41:18.953 if blo < bhi:
2025-07-02 06:41:18.953 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.953 else:
2025-07-02 06:41:18.953 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.953 elif blo < bhi:
2025-07-02 06:41:18.953 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.953
2025-07-02 06:41:18.953 > yield from g
2025-07-02 06:41:18.953
2025-07-02 06:41:18.953 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.953 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.953
2025-07-02 06:41:18.953 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.953 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.953 alo = 488, ahi = 1101
2025-07-02 06:41:18.953 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.953 blo = 488, bhi = 1101
2025-07-02 06:41:18.953
2025-07-02 06:41:18.954 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.954 r"""
2025-07-02 06:41:18.954 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.954 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.954 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.954 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.954
2025-07-02 06:41:18.954 Example:
2025-07-02 06:41:18.954
2025-07-02 06:41:18.954 >>> d = Differ()
2025-07-02 06:41:18.954 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.954 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.954 >>> print(''.join(results), end="")
2025-07-02 06:41:18.954 - abcDefghiJkl
2025-07-02 06:41:18.954 + abcdefGhijkl
2025-07-02 06:41:18.954 """
2025-07-02 06:41:18.955
2025-07-02 06:41:18.955 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.955 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.955 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.955 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.955 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.955
2025-07-02 06:41:18.955 # search for the pair that matches best without being identical
2025-07-02 06:41:18.955 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.955 # on junk -- unless we have to)
2025-07-02 06:41:18.955 for j in range(blo, bhi):
2025-07-02 06:41:18.955 bj = b[j]
2025-07-02 06:41:18.955 cruncher.set_seq2(bj)
2025-07-02 06:41:18.955 for i in range(alo, ahi):
2025-07-02 06:41:18.955 ai = a[i]
2025-07-02 06:41:18.955 if ai == bj:
2025-07-02 06:41:18.955 if eqi is None:
2025-07-02 06:41:18.955 eqi, eqj = i, j
2025-07-02 06:41:18.955 continue
2025-07-02 06:41:18.955 cruncher.set_seq1(ai)
2025-07-02 06:41:18.956 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.956 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.956 # compares by a factor of 3.
2025-07-02 06:41:18.956 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.956 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.956 # of the computation is cached by cruncher
2025-07-02 06:41:18.956 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.956 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.956 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.956 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.956 if best_ratio < cutoff:
2025-07-02 06:41:18.956 # no non-identical "pretty close" pair
2025-07-02 06:41:18.956 if eqi is None:
2025-07-02 06:41:18.956 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.956 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.956 return
2025-07-02 06:41:18.956 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.956 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.956 else:
2025-07-02 06:41:18.957 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.957 eqi = None
2025-07-02 06:41:18.957
2025-07-02 06:41:18.957 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.957 # identical
2025-07-02 06:41:18.957
2025-07-02 06:41:18.957 # pump out diffs from before the synch point
2025-07-02 06:41:18.957 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.957
2025-07-02 06:41:18.957 # do intraline marking on the synch pair
2025-07-02 06:41:18.957 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.957 if eqi is None:
2025-07-02 06:41:18.957 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.957 atags = btags = ""
2025-07-02 06:41:18.957 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.957 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.957 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.957 if tag == 'replace':
2025-07-02 06:41:18.957 atags += '^' * la
2025-07-02 06:41:18.957 btags += '^' * lb
2025-07-02 06:41:18.957 elif tag == 'delete':
2025-07-02 06:41:18.958 atags += '-' * la
2025-07-02 06:41:18.958 elif tag == 'insert':
2025-07-02 06:41:18.958 btags += '+' * lb
2025-07-02 06:41:18.958 elif tag == 'equal':
2025-07-02 06:41:18.958 atags += ' ' * la
2025-07-02 06:41:18.958 btags += ' ' * lb
2025-07-02 06:41:18.958 else:
2025-07-02 06:41:18.958 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.958 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.958 else:
2025-07-02 06:41:18.958 # the synch pair is identical
2025-07-02 06:41:18.958 yield ' ' + aelt
2025-07-02 06:41:18.958
2025-07-02 06:41:18.958 # pump out diffs from after the synch point
2025-07-02 06:41:18.958 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.958
2025-07-02 06:41:18.958 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.959 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.959
2025-07-02 06:41:18.959 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.959 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.959 alo = 489, ahi = 1101
2025-07-02 06:41:18.959 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.959 blo = 489, bhi = 1101
2025-07-02 06:41:18.959
2025-07-02 06:41:18.959 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.959 g = []
2025-07-02 06:41:18.959 if alo < ahi:
2025-07-02 06:41:18.959 if blo < bhi:
2025-07-02 06:41:18.959 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.959 else:
2025-07-02 06:41:18.959 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.959 elif blo < bhi:
2025-07-02 06:41:18.959 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.959
2025-07-02 06:41:18.959 > yield from g
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.960 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.960 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.960 alo = 489, ahi = 1101
2025-07-02 06:41:18.960 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.960 blo = 489, bhi = 1101
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.960 r"""
2025-07-02 06:41:18.960 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.960 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.960 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.960 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 Example:
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 >>> d = Differ()
2025-07-02 06:41:18.961 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.961 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.961 >>> print(''.join(results), end="")
2025-07-02 06:41:18.961 - abcDefghiJkl
2025-07-02 06:41:18.961 + abcdefGhijkl
2025-07-02 06:41:18.961 """
2025-07-02 06:41:18.961
2025-07-02 06:41:18.961 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.961 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.961 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.961 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.961 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.961
2025-07-02 06:41:18.961 # search for the pair that matches best without being identical
2025-07-02 06:41:18.961 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.961 # on junk -- unless we have to)
2025-07-02 06:41:18.961 for j in range(blo, bhi):
2025-07-02 06:41:18.962 bj = b[j]
2025-07-02 06:41:18.962 cruncher.set_seq2(bj)
2025-07-02 06:41:18.962 for i in range(alo, ahi):
2025-07-02 06:41:18.962 ai = a[i]
2025-07-02 06:41:18.962 if ai == bj:
2025-07-02 06:41:18.962 if eqi is None:
2025-07-02 06:41:18.962 eqi, eqj = i, j
2025-07-02 06:41:18.962 continue
2025-07-02 06:41:18.962 cruncher.set_seq1(ai)
2025-07-02 06:41:18.962 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.962 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.962 # compares by a factor of 3.
2025-07-02 06:41:18.962 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.962 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.962 # of the computation is cached by cruncher
2025-07-02 06:41:18.962 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.962 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.962 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.962 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.962 if best_ratio < cutoff:
2025-07-02 06:41:18.963 # no non-identical "pretty close" pair
2025-07-02 06:41:18.963 if eqi is None:
2025-07-02 06:41:18.963 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.963 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.963 return
2025-07-02 06:41:18.963 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.963 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.963 else:
2025-07-02 06:41:18.963 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.963 eqi = None
2025-07-02 06:41:18.963
2025-07-02 06:41:18.963 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.963 # identical
2025-07-02 06:41:18.963
2025-07-02 06:41:18.963 # pump out diffs from before the synch point
2025-07-02 06:41:18.963 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.963
2025-07-02 06:41:18.964 # do intraline marking on the synch pair
2025-07-02 06:41:18.964 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.964 if eqi is None:
2025-07-02 06:41:18.964 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.964 atags = btags = ""
2025-07-02 06:41:18.964 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.964 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.964 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.964 if tag == 'replace':
2025-07-02 06:41:18.964 atags += '^' * la
2025-07-02 06:41:18.964 btags += '^' * lb
2025-07-02 06:41:18.964 elif tag == 'delete':
2025-07-02 06:41:18.964 atags += '-' * la
2025-07-02 06:41:18.964 elif tag == 'insert':
2025-07-02 06:41:18.964 btags += '+' * lb
2025-07-02 06:41:18.964 elif tag == 'equal':
2025-07-02 06:41:18.964 atags += ' ' * la
2025-07-02 06:41:18.964 btags += ' ' * lb
2025-07-02 06:41:18.964 else:
2025-07-02 06:41:18.965 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.965 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.965 else:
2025-07-02 06:41:18.965 # the synch pair is identical
2025-07-02 06:41:18.965 yield ' ' + aelt
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965 # pump out diffs from after the synch point
2025-07-02 06:41:18.965 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.965 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.965 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.965 alo = 490, ahi = 1101
2025-07-02 06:41:18.965 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.965 blo = 490, bhi = 1101
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.966 g = []
2025-07-02 06:41:18.966 if alo < ahi:
2025-07-02 06:41:18.966 if blo < bhi:
2025-07-02 06:41:18.966 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.966 else:
2025-07-02 06:41:18.966 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.966 elif blo < bhi:
2025-07-02 06:41:18.966 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.966
2025-07-02 06:41:18.966 > yield from g
2025-07-02 06:41:18.966
2025-07-02 06:41:18.966 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.966 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.966
2025-07-02 06:41:18.966 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.966 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.966 alo = 490, ahi = 1101
2025-07-02 06:41:18.966 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.966 blo = 490, bhi = 1101
2025-07-02 06:41:18.967
2025-07-02 06:41:18.967 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.967 r"""
2025-07-02 06:41:18.967 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.967 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.967 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.967 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.967
2025-07-02 06:41:18.967 Example:
2025-07-02 06:41:18.967
2025-07-02 06:41:18.967 >>> d = Differ()
2025-07-02 06:41:18.967 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.967 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.967 >>> print(''.join(results), end="")
2025-07-02 06:41:18.967 - abcDefghiJkl
2025-07-02 06:41:18.967 + abcdefGhijkl
2025-07-02 06:41:18.967 """
2025-07-02 06:41:18.967
2025-07-02 06:41:18.968 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.968 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.968 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.968 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.968 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.968
2025-07-02 06:41:18.968 # search for the pair that matches best without being identical
2025-07-02 06:41:18.968 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.968 # on junk -- unless we have to)
2025-07-02 06:41:18.968 for j in range(blo, bhi):
2025-07-02 06:41:18.968 bj = b[j]
2025-07-02 06:41:18.968 cruncher.set_seq2(bj)
2025-07-02 06:41:18.968 for i in range(alo, ahi):
2025-07-02 06:41:18.968 ai = a[i]
2025-07-02 06:41:18.968 if ai == bj:
2025-07-02 06:41:18.968 if eqi is None:
2025-07-02 06:41:18.968 eqi, eqj = i, j
2025-07-02 06:41:18.968 continue
2025-07-02 06:41:18.968 cruncher.set_seq1(ai)
2025-07-02 06:41:18.969 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.969 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.969 # compares by a factor of 3.
2025-07-02 06:41:18.969 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.969 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.969 # of the computation is cached by cruncher
2025-07-02 06:41:18.969 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.969 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.969 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.969 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.969 if best_ratio < cutoff:
2025-07-02 06:41:18.969 # no non-identical "pretty close" pair
2025-07-02 06:41:18.969 if eqi is None:
2025-07-02 06:41:18.969 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.969 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.969 return
2025-07-02 06:41:18.969 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.969 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.969 else:
2025-07-02 06:41:18.969 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.970 eqi = None
2025-07-02 06:41:18.970
2025-07-02 06:41:18.970 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.970 # identical
2025-07-02 06:41:18.970
2025-07-02 06:41:18.970 # pump out diffs from before the synch point
2025-07-02 06:41:18.970 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.970
2025-07-02 06:41:18.970 # do intraline marking on the synch pair
2025-07-02 06:41:18.970 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.970 if eqi is None:
2025-07-02 06:41:18.970 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.970 atags = btags = ""
2025-07-02 06:41:18.970 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.970 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.970 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.970 if tag == 'replace':
2025-07-02 06:41:18.970 atags += '^' * la
2025-07-02 06:41:18.970 btags += '^' * lb
2025-07-02 06:41:18.971 elif tag == 'delete':
2025-07-02 06:41:18.971 atags += '-' * la
2025-07-02 06:41:18.971 elif tag == 'insert':
2025-07-02 06:41:18.971 btags += '+' * lb
2025-07-02 06:41:18.971 elif tag == 'equal':
2025-07-02 06:41:18.971 atags += ' ' * la
2025-07-02 06:41:18.971 btags += ' ' * lb
2025-07-02 06:41:18.971 else:
2025-07-02 06:41:18.971 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.971 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.971 else:
2025-07-02 06:41:18.971 # the synch pair is identical
2025-07-02 06:41:18.971 yield ' ' + aelt
2025-07-02 06:41:18.971
2025-07-02 06:41:18.971 # pump out diffs from after the synch point
2025-07-02 06:41:18.971 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.971
2025-07-02 06:41:18.971 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.971 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.971
2025-07-02 06:41:18.972 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.972 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.972 alo = 491, ahi = 1101
2025-07-02 06:41:18.972 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.972 blo = 491, bhi = 1101
2025-07-02 06:41:18.972
2025-07-02 06:41:18.972 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.972 g = []
2025-07-02 06:41:18.972 if alo < ahi:
2025-07-02 06:41:18.972 if blo < bhi:
2025-07-02 06:41:18.972 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.972 else:
2025-07-02 06:41:18.972 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.972 elif blo < bhi:
2025-07-02 06:41:18.972 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.972
2025-07-02 06:41:18.972 > yield from g
2025-07-02 06:41:18.972
2025-07-02 06:41:18.973 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.973 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.973
2025-07-02 06:41:18.973 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.973 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.973 alo = 491, ahi = 1101
2025-07-02 06:41:18.973 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.973 blo = 491, bhi = 1101
2025-07-02 06:41:18.973
2025-07-02 06:41:18.973 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.973 r"""
2025-07-02 06:41:18.973 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.973 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.973 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.973 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.973
2025-07-02 06:41:18.973 Example:
2025-07-02 06:41:18.973
2025-07-02 06:41:18.974 >>> d = Differ()
2025-07-02 06:41:18.974 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.974 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.974 >>> print(''.join(results), end="")
2025-07-02 06:41:18.974 - abcDefghiJkl
2025-07-02 06:41:18.974 + abcdefGhijkl
2025-07-02 06:41:18.974 """
2025-07-02 06:41:18.974
2025-07-02 06:41:18.974 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.974 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.974 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.974 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.974 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.974
2025-07-02 06:41:18.974 # search for the pair that matches best without being identical
2025-07-02 06:41:18.974 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.974 # on junk -- unless we have to)
2025-07-02 06:41:18.975 for j in range(blo, bhi):
2025-07-02 06:41:18.975 bj = b[j]
2025-07-02 06:41:18.975 cruncher.set_seq2(bj)
2025-07-02 06:41:18.975 for i in range(alo, ahi):
2025-07-02 06:41:18.975 ai = a[i]
2025-07-02 06:41:18.975 if ai == bj:
2025-07-02 06:41:18.975 if eqi is None:
2025-07-02 06:41:18.975 eqi, eqj = i, j
2025-07-02 06:41:18.975 continue
2025-07-02 06:41:18.975 cruncher.set_seq1(ai)
2025-07-02 06:41:18.975 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.975 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.975 # compares by a factor of 3.
2025-07-02 06:41:18.975 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.975 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.975 # of the computation is cached by cruncher
2025-07-02 06:41:18.975 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.975 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.975 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.975 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.976 if best_ratio < cutoff:
2025-07-02 06:41:18.976 # no non-identical "pretty close" pair
2025-07-02 06:41:18.976 if eqi is None:
2025-07-02 06:41:18.976 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.976 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.976 return
2025-07-02 06:41:18.976 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.976 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.976 else:
2025-07-02 06:41:18.976 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.976 eqi = None
2025-07-02 06:41:18.976
2025-07-02 06:41:18.976 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.976 # identical
2025-07-02 06:41:18.976
2025-07-02 06:41:18.976 # pump out diffs from before the synch point
2025-07-02 06:41:18.976 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.976
2025-07-02 06:41:18.976 # do intraline marking on the synch pair
2025-07-02 06:41:18.977 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.977 if eqi is None:
2025-07-02 06:41:18.977 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.977 atags = btags = ""
2025-07-02 06:41:18.977 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.977 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.977 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.977 if tag == 'replace':
2025-07-02 06:41:18.977 atags += '^' * la
2025-07-02 06:41:18.977 btags += '^' * lb
2025-07-02 06:41:18.977 elif tag == 'delete':
2025-07-02 06:41:18.977 atags += '-' * la
2025-07-02 06:41:18.977 elif tag == 'insert':
2025-07-02 06:41:18.977 btags += '+' * lb
2025-07-02 06:41:18.977 elif tag == 'equal':
2025-07-02 06:41:18.977 atags += ' ' * la
2025-07-02 06:41:18.977 btags += ' ' * lb
2025-07-02 06:41:18.977 else:
2025-07-02 06:41:18.977 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.977 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.978 else:
2025-07-02 06:41:18.978 # the synch pair is identical
2025-07-02 06:41:18.978 yield ' ' + aelt
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978 # pump out diffs from after the synch point
2025-07-02 06:41:18.978 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.978 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.978 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.978 alo = 492, ahi = 1101
2025-07-02 06:41:18.978 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.978 blo = 492, bhi = 1101
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.978 g = []
2025-07-02 06:41:18.978 if alo < ahi:
2025-07-02 06:41:18.979 if blo < bhi:
2025-07-02 06:41:18.979 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.979 else:
2025-07-02 06:41:18.979 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.979 elif blo < bhi:
2025-07-02 06:41:18.979 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 > yield from g
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.979 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.979 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.979 alo = 492, ahi = 1101
2025-07-02 06:41:18.979 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.979 blo = 492, bhi = 1101
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.979 r"""
2025-07-02 06:41:18.980 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.980 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.980 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.980 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.980
2025-07-02 06:41:18.980 Example:
2025-07-02 06:41:18.980
2025-07-02 06:41:18.980 >>> d = Differ()
2025-07-02 06:41:18.980 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.980 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.980 >>> print(''.join(results), end="")
2025-07-02 06:41:18.980 - abcDefghiJkl
2025-07-02 06:41:18.980 + abcdefGhijkl
2025-07-02 06:41:18.980 """
2025-07-02 06:41:18.980
2025-07-02 06:41:18.980 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.980 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.981 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.981 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.981 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.981
2025-07-02 06:41:18.981 # search for the pair that matches best without being identical
2025-07-02 06:41:18.981 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.981 # on junk -- unless we have to)
2025-07-02 06:41:18.981 for j in range(blo, bhi):
2025-07-02 06:41:18.981 bj = b[j]
2025-07-02 06:41:18.981 cruncher.set_seq2(bj)
2025-07-02 06:41:18.981 for i in range(alo, ahi):
2025-07-02 06:41:18.981 ai = a[i]
2025-07-02 06:41:18.981 if ai == bj:
2025-07-02 06:41:18.981 if eqi is None:
2025-07-02 06:41:18.981 eqi, eqj = i, j
2025-07-02 06:41:18.981 continue
2025-07-02 06:41:18.981 cruncher.set_seq1(ai)
2025-07-02 06:41:18.981 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.981 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.982 # compares by a factor of 3.
2025-07-02 06:41:18.982 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.982 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.982 # of the computation is cached by cruncher
2025-07-02 06:41:18.982 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.982 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.982 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.982 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.982 if best_ratio < cutoff:
2025-07-02 06:41:18.982 # no non-identical "pretty close" pair
2025-07-02 06:41:18.982 if eqi is None:
2025-07-02 06:41:18.982 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.982 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.982 return
2025-07-02 06:41:18.982 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.982 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.982 else:
2025-07-02 06:41:18.982 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.982 eqi = None
2025-07-02 06:41:18.983
2025-07-02 06:41:18.983 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.983 # identical
2025-07-02 06:41:18.983
2025-07-02 06:41:18.983 # pump out diffs from before the synch point
2025-07-02 06:41:18.983 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.983
2025-07-02 06:41:18.983 # do intraline marking on the synch pair
2025-07-02 06:41:18.983 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.983 if eqi is None:
2025-07-02 06:41:18.983 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.983 atags = btags = ""
2025-07-02 06:41:18.983 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.983 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.983 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.983 if tag == 'replace':
2025-07-02 06:41:18.983 atags += '^' * la
2025-07-02 06:41:18.983 btags += '^' * lb
2025-07-02 06:41:18.983 elif tag == 'delete':
2025-07-02 06:41:18.984 atags += '-' * la
2025-07-02 06:41:18.984 elif tag == 'insert':
2025-07-02 06:41:18.984 btags += '+' * lb
2025-07-02 06:41:18.984 elif tag == 'equal':
2025-07-02 06:41:18.984 atags += ' ' * la
2025-07-02 06:41:18.984 btags += ' ' * lb
2025-07-02 06:41:18.984 else:
2025-07-02 06:41:18.984 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.984 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.984 else:
2025-07-02 06:41:18.984 # the synch pair is identical
2025-07-02 06:41:18.984 yield ' ' + aelt
2025-07-02 06:41:18.984
2025-07-02 06:41:18.984 # pump out diffs from after the synch point
2025-07-02 06:41:18.984 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.984
2025-07-02 06:41:18.984 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.984 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.984
2025-07-02 06:41:18.984 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.985 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.985 alo = 493, ahi = 1101
2025-07-02 06:41:18.985 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.985 blo = 493, bhi = 1101
2025-07-02 06:41:18.985
2025-07-02 06:41:18.985 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.985 g = []
2025-07-02 06:41:18.985 if alo < ahi:
2025-07-02 06:41:18.985 if blo < bhi:
2025-07-02 06:41:18.985 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.985 else:
2025-07-02 06:41:18.985 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.985 elif blo < bhi:
2025-07-02 06:41:18.985 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.985
2025-07-02 06:41:18.985 > yield from g
2025-07-02 06:41:18.985
2025-07-02 06:41:18.985 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.986 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.986 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.986 alo = 493, ahi = 1101
2025-07-02 06:41:18.986 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.986 blo = 493, bhi = 1101
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.986 r"""
2025-07-02 06:41:18.986 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.986 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.986 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.986 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986 Example:
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986 >>> d = Differ()
2025-07-02 06:41:18.986 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.987 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.987 >>> print(''.join(results), end="")
2025-07-02 06:41:18.987 - abcDefghiJkl
2025-07-02 06:41:18.987 + abcdefGhijkl
2025-07-02 06:41:18.987 """
2025-07-02 06:41:18.987
2025-07-02 06:41:18.987 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.987 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.987 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.987 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.987 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.987
2025-07-02 06:41:18.987 # search for the pair that matches best without being identical
2025-07-02 06:41:18.987 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.987 # on junk -- unless we have to)
2025-07-02 06:41:18.987 for j in range(blo, bhi):
2025-07-02 06:41:18.987 bj = b[j]
2025-07-02 06:41:18.988 cruncher.set_seq2(bj)
2025-07-02 06:41:18.988 for i in range(alo, ahi):
2025-07-02 06:41:18.988 ai = a[i]
2025-07-02 06:41:18.988 if ai == bj:
2025-07-02 06:41:18.988 if eqi is None:
2025-07-02 06:41:18.988 eqi, eqj = i, j
2025-07-02 06:41:18.988 continue
2025-07-02 06:41:18.988 cruncher.set_seq1(ai)
2025-07-02 06:41:18.988 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.988 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.988 # compares by a factor of 3.
2025-07-02 06:41:18.988 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.988 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.988 # of the computation is cached by cruncher
2025-07-02 06:41:18.988 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.988 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.988 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.988 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.988 if best_ratio < cutoff:
2025-07-02 06:41:18.988 # no non-identical "pretty close" pair
2025-07-02 06:41:18.989 if eqi is None:
2025-07-02 06:41:18.989 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.989 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.989 return
2025-07-02 06:41:18.989 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.989 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.989 else:
2025-07-02 06:41:18.989 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.989 eqi = None
2025-07-02 06:41:18.989
2025-07-02 06:41:18.989 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.989 # identical
2025-07-02 06:41:18.989
2025-07-02 06:41:18.989 # pump out diffs from before the synch point
2025-07-02 06:41:18.989 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.989
2025-07-02 06:41:18.989 # do intraline marking on the synch pair
2025-07-02 06:41:18.990 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.990 if eqi is None:
2025-07-02 06:41:18.990 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.990 atags = btags = ""
2025-07-02 06:41:18.990 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.990 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.990 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.990 if tag == 'replace':
2025-07-02 06:41:18.990 atags += '^' * la
2025-07-02 06:41:18.990 btags += '^' * lb
2025-07-02 06:41:18.990 elif tag == 'delete':
2025-07-02 06:41:18.990 atags += '-' * la
2025-07-02 06:41:18.990 elif tag == 'insert':
2025-07-02 06:41:18.990 btags += '+' * lb
2025-07-02 06:41:18.990 elif tag == 'equal':
2025-07-02 06:41:18.990 atags += ' ' * la
2025-07-02 06:41:18.990 btags += ' ' * lb
2025-07-02 06:41:18.990 else:
2025-07-02 06:41:18.991 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.991 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.991 else:
2025-07-02 06:41:18.991 # the synch pair is identical
2025-07-02 06:41:18.991 yield ' ' + aelt
2025-07-02 06:41:18.991
2025-07-02 06:41:18.991 # pump out diffs from after the synch point
2025-07-02 06:41:18.991 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.991
2025-07-02 06:41:18.991 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.991 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.991
2025-07-02 06:41:18.991 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.991 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.991 alo = 494, ahi = 1101
2025-07-02 06:41:18.991 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.991 blo = 494, bhi = 1101
2025-07-02 06:41:18.991
2025-07-02 06:41:18.992 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.992 g = []
2025-07-02 06:41:18.992 if alo < ahi:
2025-07-02 06:41:18.992 if blo < bhi:
2025-07-02 06:41:18.992 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.992 else:
2025-07-02 06:41:18.992 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.992 elif blo < bhi:
2025-07-02 06:41:18.992 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.992
2025-07-02 06:41:18.992 > yield from g
2025-07-02 06:41:18.992
2025-07-02 06:41:18.992 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.992 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.992
2025-07-02 06:41:18.992 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.992 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.992 alo = 494, ahi = 1101
2025-07-02 06:41:18.993 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.993 blo = 494, bhi = 1101
2025-07-02 06:41:18.993
2025-07-02 06:41:18.993 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.993 r"""
2025-07-02 06:41:18.993 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.993 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.993 synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.993 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.993
2025-07-02 06:41:18.993 Example:
2025-07-02 06:41:18.993
2025-07-02 06:41:18.993 >>> d = Differ()
2025-07-02 06:41:18.993 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.993 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.993 >>> print(''.join(results), end="")
2025-07-02 06:41:18.993 - abcDefghiJkl
2025-07-02 06:41:18.993 + abcdefGhijkl
2025-07-02 06:41:18.994 """
2025-07-02 06:41:18.994
2025-07-02 06:41:18.994 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.994 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.994 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.994 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.994 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:18.994
2025-07-02 06:41:18.994 # search for the pair that matches best without being identical
2025-07-02 06:41:18.994 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.994 # on junk -- unless we have to)
2025-07-02 06:41:18.994 for j in range(blo, bhi):
2025-07-02 06:41:18.994 bj = b[j]
2025-07-02 06:41:18.994 cruncher.set_seq2(bj)
2025-07-02 06:41:18.994 for i in range(alo, ahi):
2025-07-02 06:41:18.994 ai = a[i]
2025-07-02 06:41:18.994 if ai == bj:
2025-07-02 06:41:18.995 if eqi is None:
2025-07-02 06:41:18.995 eqi, eqj = i, j
2025-07-02 06:41:18.995 continue
2025-07-02 06:41:18.995 cruncher.set_seq1(ai)
2025-07-02 06:41:18.995 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.995 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.995 # compares by a factor of 3.
2025-07-02 06:41:18.995 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.995 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.995 # of the computation is cached by cruncher
2025-07-02 06:41:18.995 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.995 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.995 cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.995 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.995 if best_ratio < cutoff:
2025-07-02 06:41:18.995 # no non-identical "pretty close" pair
2025-07-02 06:41:18.995 if eqi is None:
2025-07-02 06:41:18.995 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.996 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.996 return
2025-07-02 06:41:18.996 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.996 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.996 else:
2025-07-02 06:41:18.996 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.996 eqi = None
2025-07-02 06:41:18.996
2025-07-02 06:41:18.996 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.996 # identical
2025-07-02 06:41:18.996
2025-07-02 06:41:18.996 # pump out diffs from before the synch point
2025-07-02 06:41:18.996 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.996
2025-07-02 06:41:18.996 # do intraline marking on the synch pair
2025-07-02 06:41:18.996 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.996 if eqi is None:
2025-07-02 06:41:18.996 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.996 atags = btags = ""
2025-07-02 06:41:18.997 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.997 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.997 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.997 if tag == 'replace':
2025-07-02 06:41:18.997 atags += '^' * la
2025-07-02 06:41:18.997 btags += '^' * lb
2025-07-02 06:41:18.997 elif tag == 'delete':
2025-07-02 06:41:18.997 atags += '-' * la
2025-07-02 06:41:18.997 elif tag == 'insert':
2025-07-02 06:41:18.997 btags += '+' * lb
2025-07-02 06:41:18.997 elif tag == 'equal':
2025-07-02 06:41:18.997 atags += ' ' * la
2025-07-02 06:41:18.997 btags += ' ' * lb
2025-07-02 06:41:18.997 else:
2025-07-02 06:41:18.997 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.997 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.997 else:
2025-07-02 06:41:18.997 # the synch pair is identical
2025-07-02 06:41:18.997 yield ' ' + aelt
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998 # pump out diffs from after the synch point
2025-07-02 06:41:18.998 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.998 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.998 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.998 alo = 495, ahi = 1101
2025-07-02 06:41:18.998 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.998 blo = 495, bhi = 1101
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.998 g = []
2025-07-02 06:41:18.998 if alo < ahi:
2025-07-02 06:41:18.998 if blo < bhi:
2025-07-02 06:41:18.998 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.998 else:
2025-07-02 06:41:18.999 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.999 elif blo < bhi:
2025-07-02 06:41:18.999 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 > yield from g
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.999 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.999 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:18.999 alo = 495, ahi = 1101
2025-07-02 06:41:18.999 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:18.999 blo = 495, bhi = 1101
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.999 r"""
2025-07-02 06:41:19.000 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.000 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.000 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.000 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.000
2025-07-02 06:41:19.000 Example:
2025-07-02 06:41:19.000
2025-07-02 06:41:19.000 >>> d = Differ()
2025-07-02 06:41:19.000 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.000 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.000 >>> print(''.join(results), end="")
2025-07-02 06:41:19.000 - abcDefghiJkl
2025-07-02 06:41:19.000 + abcdefGhijkl
2025-07-02 06:41:19.000 """
2025-07-02 06:41:19.000
2025-07-02 06:41:19.000 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.000 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.001 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.001 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.001 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.001
2025-07-02 06:41:19.001 # search for the pair that matches best without being identical
2025-07-02 06:41:19.001 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.001 # on junk -- unless we have to)
2025-07-02 06:41:19.001 for j in range(blo, bhi):
2025-07-02 06:41:19.001 bj = b[j]
2025-07-02 06:41:19.001 cruncher.set_seq2(bj)
2025-07-02 06:41:19.001 for i in range(alo, ahi):
2025-07-02 06:41:19.001 ai = a[i]
2025-07-02 06:41:19.001 if ai == bj:
2025-07-02 06:41:19.001 if eqi is None:
2025-07-02 06:41:19.001 eqi, eqj = i, j
2025-07-02 06:41:19.001 continue
2025-07-02 06:41:19.001 cruncher.set_seq1(ai)
2025-07-02 06:41:19.001 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.001 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.002 # compares by a factor of 3.
2025-07-02 06:41:19.002 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.002 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.002 # of the computation is cached by cruncher
2025-07-02 06:41:19.002 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.002 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.002 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.002 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.002 if best_ratio < cutoff:
2025-07-02 06:41:19.002 # no non-identical "pretty close" pair
2025-07-02 06:41:19.002 if eqi is None:
2025-07-02 06:41:19.002 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.002 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.002 return
2025-07-02 06:41:19.002 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.002 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.002 else:
2025-07-02 06:41:19.002 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.002 eqi = None
2025-07-02 06:41:19.002
2025-07-02 06:41:19.003 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.003 # identical
2025-07-02 06:41:19.003
2025-07-02 06:41:19.003 # pump out diffs from before the synch point
2025-07-02 06:41:19.003 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.003
2025-07-02 06:41:19.003 # do intraline marking on the synch pair
2025-07-02 06:41:19.003 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.003 if eqi is None:
2025-07-02 06:41:19.003 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.003 atags = btags = ""
2025-07-02 06:41:19.003 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.003 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.003 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.003 if tag == 'replace':
2025-07-02 06:41:19.003 atags += '^' * la
2025-07-02 06:41:19.003 btags += '^' * lb
2025-07-02 06:41:19.003 elif tag == 'delete':
2025-07-02 06:41:19.003 atags += '-' * la
2025-07-02 06:41:19.003 elif tag == 'insert':
2025-07-02 06:41:19.003 btags += '+' * lb
2025-07-02 06:41:19.004 elif tag == 'equal':
2025-07-02 06:41:19.004 atags += ' ' * la
2025-07-02 06:41:19.004 btags += ' ' * lb
2025-07-02 06:41:19.004 else:
2025-07-02 06:41:19.004 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.004 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.004 else:
2025-07-02 06:41:19.004 # the synch pair is identical
2025-07-02 06:41:19.004 yield ' ' + aelt
2025-07-02 06:41:19.004
2025-07-02 06:41:19.004 # pump out diffs from after the synch point
2025-07-02 06:41:19.004 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.004
2025-07-02 06:41:19.004 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.004 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.004
2025-07-02 06:41:19.004 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.004 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.005 alo = 496, ahi = 1101
2025-07-02 06:41:19.005 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.005 blo = 496, bhi = 1101
2025-07-02 06:41:19.005
2025-07-02 06:41:19.005 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.005 g = []
2025-07-02 06:41:19.005 if alo < ahi:
2025-07-02 06:41:19.005 if blo < bhi:
2025-07-02 06:41:19.005 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.005 else:
2025-07-02 06:41:19.005 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.005 elif blo < bhi:
2025-07-02 06:41:19.005 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.005
2025-07-02 06:41:19.005 > yield from g
2025-07-02 06:41:19.005
2025-07-02 06:41:19.005 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.005 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.005
2025-07-02 06:41:19.006 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.006 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.006 alo = 496, ahi = 1101
2025-07-02 06:41:19.006 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.006 blo = 496, bhi = 1101
2025-07-02 06:41:19.006
2025-07-02 06:41:19.006 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.006 r"""
2025-07-02 06:41:19.006 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.006 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.006 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.006 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.006
2025-07-02 06:41:19.006 Example:
2025-07-02 06:41:19.006
2025-07-02 06:41:19.006 >>> d = Differ()
2025-07-02 06:41:19.006 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.006 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.006 >>> print(''.join(results), end="")
2025-07-02 06:41:19.007 - abcDefghiJkl
2025-07-02 06:41:19.007 + abcdefGhijkl
2025-07-02 06:41:19.007 """
2025-07-02 06:41:19.007
2025-07-02 06:41:19.007 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.007 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.007 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.007 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.007 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.007
2025-07-02 06:41:19.007 # search for the pair that matches best without being identical
2025-07-02 06:41:19.007 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.007 # on junk -- unless we have to)
2025-07-02 06:41:19.007 for j in range(blo, bhi):
2025-07-02 06:41:19.007 bj = b[j]
2025-07-02 06:41:19.007 cruncher.set_seq2(bj)
2025-07-02 06:41:19.007 for i in range(alo, ahi):
2025-07-02 06:41:19.007 ai = a[i]
2025-07-02 06:41:19.008 if ai == bj:
2025-07-02 06:41:19.008 if eqi is None:
2025-07-02 06:41:19.008 eqi, eqj = i, j
2025-07-02 06:41:19.008 continue
2025-07-02 06:41:19.008 cruncher.set_seq1(ai)
2025-07-02 06:41:19.008 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.008 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.008 # compares by a factor of 3.
2025-07-02 06:41:19.008 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.008 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.008 # of the computation is cached by cruncher
2025-07-02 06:41:19.008 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.008 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.008 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.008 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.008 if best_ratio < cutoff:
2025-07-02 06:41:19.008 # no non-identical "pretty close" pair
2025-07-02 06:41:19.008 if eqi is None:
2025-07-02 06:41:19.008 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.009 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.009 return
2025-07-02 06:41:19.009 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.009 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.009 else:
2025-07-02 06:41:19.009 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.009 eqi = None
2025-07-02 06:41:19.009
2025-07-02 06:41:19.009 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.009 # identical
2025-07-02 06:41:19.009
2025-07-02 06:41:19.009 # pump out diffs from before the synch point
2025-07-02 06:41:19.009 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.009
2025-07-02 06:41:19.009 # do intraline marking on the synch pair
2025-07-02 06:41:19.009 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.009 if eqi is None:
2025-07-02 06:41:19.009 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.010 atags = btags = ""
2025-07-02 06:41:19.010 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.010 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.010 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.010 if tag == 'replace':
2025-07-02 06:41:19.010 atags += '^' * la
2025-07-02 06:41:19.010 btags += '^' * lb
2025-07-02 06:41:19.010 elif tag == 'delete':
2025-07-02 06:41:19.010 atags += '-' * la
2025-07-02 06:41:19.010 elif tag == 'insert':
2025-07-02 06:41:19.010 btags += '+' * lb
2025-07-02 06:41:19.010 elif tag == 'equal':
2025-07-02 06:41:19.010 atags += ' ' * la
2025-07-02 06:41:19.010 btags += ' ' * lb
2025-07-02 06:41:19.010 else:
2025-07-02 06:41:19.010 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.010 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.010 else:
2025-07-02 06:41:19.010 # the synch pair is identical
2025-07-02 06:41:19.011 yield ' ' + aelt
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011 # pump out diffs from after the synch point
2025-07-02 06:41:19.011 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.011 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.011 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.011 alo = 497, ahi = 1101
2025-07-02 06:41:19.011 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.011 blo = 497, bhi = 1101
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.011 g = []
2025-07-02 06:41:19.011 if alo < ahi:
2025-07-02 06:41:19.011 if blo < bhi:
2025-07-02 06:41:19.011 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.011 else:
2025-07-02 06:41:19.012 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.012 elif blo < bhi:
2025-07-02 06:41:19.012 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 > yield from g
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.012 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.012 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.012 alo = 497, ahi = 1101
2025-07-02 06:41:19.012 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.012 blo = 497, bhi = 1101
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.012 r"""
2025-07-02 06:41:19.012 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.012 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.012 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.013 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013 Example:
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013 >>> d = Differ()
2025-07-02 06:41:19.013 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.013 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.013 >>> print(''.join(results), end="")
2025-07-02 06:41:19.013 - abcDefghiJkl
2025-07-02 06:41:19.013 + abcdefGhijkl
2025-07-02 06:41:19.013 """
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.013 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.013 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.013 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.013 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013 # search for the pair that matches best without being identical
2025-07-02 06:41:19.014 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.014 # on junk -- unless we have to)
2025-07-02 06:41:19.014 for j in range(blo, bhi):
2025-07-02 06:41:19.014 bj = b[j]
2025-07-02 06:41:19.014 cruncher.set_seq2(bj)
2025-07-02 06:41:19.014 for i in range(alo, ahi):
2025-07-02 06:41:19.014 ai = a[i]
2025-07-02 06:41:19.014 if ai == bj:
2025-07-02 06:41:19.014 if eqi is None:
2025-07-02 06:41:19.014 eqi, eqj = i, j
2025-07-02 06:41:19.014 continue
2025-07-02 06:41:19.014 cruncher.set_seq1(ai)
2025-07-02 06:41:19.014 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.014 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.014 # compares by a factor of 3.
2025-07-02 06:41:19.014 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.014 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.014 # of the computation is cached by cruncher
2025-07-02 06:41:19.014 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.014 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.015 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.015 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.015 if best_ratio < cutoff:
2025-07-02 06:41:19.015 # no non-identical "pretty close" pair
2025-07-02 06:41:19.015 if eqi is None:
2025-07-02 06:41:19.015 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.015 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.015 return
2025-07-02 06:41:19.015 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.015 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.015 else:
2025-07-02 06:41:19.015 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.015 eqi = None
2025-07-02 06:41:19.015
2025-07-02 06:41:19.015 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.015 # identical
2025-07-02 06:41:19.015
2025-07-02 06:41:19.015 # pump out diffs from before the synch point
2025-07-02 06:41:19.015 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.015
2025-07-02 06:41:19.016 # do intraline marking on the synch pair
2025-07-02 06:41:19.016 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.016 if eqi is None:
2025-07-02 06:41:19.016 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.016 atags = btags = ""
2025-07-02 06:41:19.016 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.016 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.016 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.016 if tag == 'replace':
2025-07-02 06:41:19.016 atags += '^' * la
2025-07-02 06:41:19.016 btags += '^' * lb
2025-07-02 06:41:19.016 elif tag == 'delete':
2025-07-02 06:41:19.016 atags += '-' * la
2025-07-02 06:41:19.016 elif tag == 'insert':
2025-07-02 06:41:19.016 btags += '+' * lb
2025-07-02 06:41:19.016 elif tag == 'equal':
2025-07-02 06:41:19.016 atags += ' ' * la
2025-07-02 06:41:19.016 btags += ' ' * lb
2025-07-02 06:41:19.016 else:
2025-07-02 06:41:19.016 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.016 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.017 else:
2025-07-02 06:41:19.017 # the synch pair is identical
2025-07-02 06:41:19.017 yield ' ' + aelt
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017 # pump out diffs from after the synch point
2025-07-02 06:41:19.017 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.017 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.017 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.017 alo = 498, ahi = 1101
2025-07-02 06:41:19.017 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.017 blo = 498, bhi = 1101
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.017 g = []
2025-07-02 06:41:19.018 if alo < ahi:
2025-07-02 06:41:19.018 if blo < bhi:
2025-07-02 06:41:19.018 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.018 else:
2025-07-02 06:41:19.018 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.018 elif blo < bhi:
2025-07-02 06:41:19.018 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.018
2025-07-02 06:41:19.018 > yield from g
2025-07-02 06:41:19.018
2025-07-02 06:41:19.018 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.018 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.018
2025-07-02 06:41:19.018 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.018 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.018 alo = 498, ahi = 1101
2025-07-02 06:41:19.018 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.018 blo = 498, bhi = 1101
2025-07-02 06:41:19.018
2025-07-02 06:41:19.019 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.019 r"""
2025-07-02 06:41:19.019 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.019 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.019 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.019 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.019
2025-07-02 06:41:19.019 Example:
2025-07-02 06:41:19.019
2025-07-02 06:41:19.019 >>> d = Differ()
2025-07-02 06:41:19.019 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.019 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.019 >>> print(''.join(results), end="")
2025-07-02 06:41:19.019 - abcDefghiJkl
2025-07-02 06:41:19.019 + abcdefGhijkl
2025-07-02 06:41:19.019 """
2025-07-02 06:41:19.019
2025-07-02 06:41:19.019 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.020 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.020 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.020 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.020 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.020
2025-07-02 06:41:19.020 # search for the pair that matches best without being identical
2025-07-02 06:41:19.020 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.020 # on junk -- unless we have to)
2025-07-02 06:41:19.020 for j in range(blo, bhi):
2025-07-02 06:41:19.020 bj = b[j]
2025-07-02 06:41:19.020 cruncher.set_seq2(bj)
2025-07-02 06:41:19.020 for i in range(alo, ahi):
2025-07-02 06:41:19.020 ai = a[i]
2025-07-02 06:41:19.020 if ai == bj:
2025-07-02 06:41:19.020 if eqi is None:
2025-07-02 06:41:19.020 eqi, eqj = i, j
2025-07-02 06:41:19.020 continue
2025-07-02 06:41:19.020 cruncher.set_seq1(ai)
2025-07-02 06:41:19.020 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.020 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.021 # compares by a factor of 3.
2025-07-02 06:41:19.021 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.021 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.021 # of the computation is cached by cruncher
2025-07-02 06:41:19.021 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.021 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.021 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.021 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.021 if best_ratio < cutoff:
2025-07-02 06:41:19.021 # no non-identical "pretty close" pair
2025-07-02 06:41:19.021 if eqi is None:
2025-07-02 06:41:19.021 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.021 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.021 return
2025-07-02 06:41:19.021 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.021 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.021 else:
2025-07-02 06:41:19.021 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.022 eqi = None
2025-07-02 06:41:19.022
2025-07-02 06:41:19.022 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.022 # identical
2025-07-02 06:41:19.022
2025-07-02 06:41:19.022 # pump out diffs from before the synch point
2025-07-02 06:41:19.022 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.022
2025-07-02 06:41:19.022 # do intraline marking on the synch pair
2025-07-02 06:41:19.022 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.022 if eqi is None:
2025-07-02 06:41:19.022 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.022 atags = btags = ""
2025-07-02 06:41:19.022 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.022 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.022 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.022 if tag == 'replace':
2025-07-02 06:41:19.022 atags += '^' * la
2025-07-02 06:41:19.022 btags += '^' * lb
2025-07-02 06:41:19.023 elif tag == 'delete':
2025-07-02 06:41:19.023 atags += '-' * la
2025-07-02 06:41:19.023 elif tag == 'insert':
2025-07-02 06:41:19.023 btags += '+' * lb
2025-07-02 06:41:19.023 elif tag == 'equal':
2025-07-02 06:41:19.023 atags += ' ' * la
2025-07-02 06:41:19.023 btags += ' ' * lb
2025-07-02 06:41:19.023 else:
2025-07-02 06:41:19.023 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.023 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.023 else:
2025-07-02 06:41:19.023 # the synch pair is identical
2025-07-02 06:41:19.023 yield ' ' + aelt
2025-07-02 06:41:19.023
2025-07-02 06:41:19.023 # pump out diffs from after the synch point
2025-07-02 06:41:19.023 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.023
2025-07-02 06:41:19.023 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.023 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.024 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.024 alo = 499, ahi = 1101
2025-07-02 06:41:19.024 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.024 blo = 499, bhi = 1101
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.024 g = []
2025-07-02 06:41:19.024 if alo < ahi:
2025-07-02 06:41:19.024 if blo < bhi:
2025-07-02 06:41:19.024 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.024 else:
2025-07-02 06:41:19.024 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.024 elif blo < bhi:
2025-07-02 06:41:19.024 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 > yield from g
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.025 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.025 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.025 alo = 499, ahi = 1101
2025-07-02 06:41:19.025 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.025 blo = 499, bhi = 1101
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.025 r"""
2025-07-02 06:41:19.025 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.025 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.025 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.025 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025 Example:
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025 >>> d = Differ()
2025-07-02 06:41:19.025 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.025 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.026 >>> print(''.join(results), end="")
2025-07-02 06:41:19.026 - abcDefghiJkl
2025-07-02 06:41:19.026 + abcdefGhijkl
2025-07-02 06:41:19.026 """
2025-07-02 06:41:19.026
2025-07-02 06:41:19.026 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.026 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.026 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.026 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.026 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.026
2025-07-02 06:41:19.026 # search for the pair that matches best without being identical
2025-07-02 06:41:19.026 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.026 # on junk -- unless we have to)
2025-07-02 06:41:19.026 for j in range(blo, bhi):
2025-07-02 06:41:19.026 bj = b[j]
2025-07-02 06:41:19.026 cruncher.set_seq2(bj)
2025-07-02 06:41:19.027 for i in range(alo, ahi):
2025-07-02 06:41:19.027 ai = a[i]
2025-07-02 06:41:19.027 if ai == bj:
2025-07-02 06:41:19.027 if eqi is None:
2025-07-02 06:41:19.027 eqi, eqj = i, j
2025-07-02 06:41:19.027 continue
2025-07-02 06:41:19.027 cruncher.set_seq1(ai)
2025-07-02 06:41:19.027 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.027 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.027 # compares by a factor of 3.
2025-07-02 06:41:19.027 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.027 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.027 # of the computation is cached by cruncher
2025-07-02 06:41:19.027 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.027 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.027 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.027 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.027 if best_ratio < cutoff:
2025-07-02 06:41:19.027 # no non-identical "pretty close" pair
2025-07-02 06:41:19.028 if eqi is None:
2025-07-02 06:41:19.028 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.028 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.028 return
2025-07-02 06:41:19.028 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.028 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.028 else:
2025-07-02 06:41:19.028 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.028 eqi = None
2025-07-02 06:41:19.028
2025-07-02 06:41:19.028 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.028 # identical
2025-07-02 06:41:19.028
2025-07-02 06:41:19.028 # pump out diffs from before the synch point
2025-07-02 06:41:19.028 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.028
2025-07-02 06:41:19.028 # do intraline marking on the synch pair
2025-07-02 06:41:19.028 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.028 if eqi is None:
2025-07-02 06:41:19.029 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.029 atags = btags = ""
2025-07-02 06:41:19.029 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.029 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.029 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.029 if tag == 'replace':
2025-07-02 06:41:19.029 atags += '^' * la
2025-07-02 06:41:19.029 btags += '^' * lb
2025-07-02 06:41:19.029 elif tag == 'delete':
2025-07-02 06:41:19.029 atags += '-' * la
2025-07-02 06:41:19.029 elif tag == 'insert':
2025-07-02 06:41:19.029 btags += '+' * lb
2025-07-02 06:41:19.029 elif tag == 'equal':
2025-07-02 06:41:19.029 atags += ' ' * la
2025-07-02 06:41:19.029 btags += ' ' * lb
2025-07-02 06:41:19.029 else:
2025-07-02 06:41:19.029 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.029 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.029 else:
2025-07-02 06:41:19.029 # the synch pair is identical
2025-07-02 06:41:19.029 yield ' ' + aelt
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030 # pump out diffs from after the synch point
2025-07-02 06:41:19.030 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.030 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.030 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.030 alo = 500, ahi = 1101
2025-07-02 06:41:19.030 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.030 blo = 500, bhi = 1101
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.030 g = []
2025-07-02 06:41:19.030 if alo < ahi:
2025-07-02 06:41:19.030 if blo < bhi:
2025-07-02 06:41:19.030 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.030 else:
2025-07-02 06:41:19.030 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.031 elif blo < bhi:
2025-07-02 06:41:19.031 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 > yield from g
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.031 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.031 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.031 alo = 500, ahi = 1101
2025-07-02 06:41:19.031 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.031 blo = 500, bhi = 1101
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.031 r"""
2025-07-02 06:41:19.031 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.031 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.031 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.031 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032 Example:
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032 >>> d = Differ()
2025-07-02 06:41:19.032 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.032 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.032 >>> print(''.join(results), end="")
2025-07-02 06:41:19.032 - abcDefghiJkl
2025-07-02 06:41:19.032 + abcdefGhijkl
2025-07-02 06:41:19.032 """
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.032 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.032 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.032 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.032 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032 # search for the pair that matches best without being identical
2025-07-02 06:41:19.033 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.033 # on junk -- unless we have to)
2025-07-02 06:41:19.033 for j in range(blo, bhi):
2025-07-02 06:41:19.033 bj = b[j]
2025-07-02 06:41:19.033 cruncher.set_seq2(bj)
2025-07-02 06:41:19.033 for i in range(alo, ahi):
2025-07-02 06:41:19.033 ai = a[i]
2025-07-02 06:41:19.033 if ai == bj:
2025-07-02 06:41:19.033 if eqi is None:
2025-07-02 06:41:19.033 eqi, eqj = i, j
2025-07-02 06:41:19.033 continue
2025-07-02 06:41:19.033 cruncher.set_seq1(ai)
2025-07-02 06:41:19.033 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.033 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.033 # compares by a factor of 3.
2025-07-02 06:41:19.033 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.033 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.033 # of the computation is cached by cruncher
2025-07-02 06:41:19.033 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.033 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.033 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.034 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.034 if best_ratio < cutoff:
2025-07-02 06:41:19.034 # no non-identical "pretty close" pair
2025-07-02 06:41:19.034 if eqi is None:
2025-07-02 06:41:19.034 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.034 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.034 return
2025-07-02 06:41:19.034 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.034 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.034 else:
2025-07-02 06:41:19.034 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.034 eqi = None
2025-07-02 06:41:19.034
2025-07-02 06:41:19.034 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.034 # identical
2025-07-02 06:41:19.034
2025-07-02 06:41:19.034 # pump out diffs from before the synch point
2025-07-02 06:41:19.034 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.034
2025-07-02 06:41:19.034 # do intraline marking on the synch pair
2025-07-02 06:41:19.035 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.035 if eqi is None:
2025-07-02 06:41:19.035 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.035 atags = btags = ""
2025-07-02 06:41:19.035 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.035 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.035 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.035 if tag == 'replace':
2025-07-02 06:41:19.035 atags += '^' * la
2025-07-02 06:41:19.035 btags += '^' * lb
2025-07-02 06:41:19.035 elif tag == 'delete':
2025-07-02 06:41:19.035 atags += '-' * la
2025-07-02 06:41:19.035 elif tag == 'insert':
2025-07-02 06:41:19.035 btags += '+' * lb
2025-07-02 06:41:19.035 elif tag == 'equal':
2025-07-02 06:41:19.035 atags += ' ' * la
2025-07-02 06:41:19.035 btags += ' ' * lb
2025-07-02 06:41:19.035 else:
2025-07-02 06:41:19.036 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.036 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.036 else:
2025-07-02 06:41:19.036 # the synch pair is identical
2025-07-02 06:41:19.036 yield ' ' + aelt
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036 # pump out diffs from after the synch point
2025-07-02 06:41:19.036 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.036 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.036 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.036 alo = 501, ahi = 1101
2025-07-02 06:41:19.036 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.036 blo = 501, bhi = 1101
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.037 g = []
2025-07-02 06:41:19.037 if alo < ahi:
2025-07-02 06:41:19.037 if blo < bhi:
2025-07-02 06:41:19.037 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.037 else:
2025-07-02 06:41:19.037 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.037 elif blo < bhi:
2025-07-02 06:41:19.037 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.037
2025-07-02 06:41:19.037 > yield from g
2025-07-02 06:41:19.037
2025-07-02 06:41:19.037 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.037 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.037
2025-07-02 06:41:19.037 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.037 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.037 alo = 501, ahi = 1101
2025-07-02 06:41:19.037 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.038 blo = 501, bhi = 1101
2025-07-02 06:41:19.038
2025-07-02 06:41:19.038 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.038 r"""
2025-07-02 06:41:19.038 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.038 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.038 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.038 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.038
2025-07-02 06:41:19.038 Example:
2025-07-02 06:41:19.038
2025-07-02 06:41:19.038 >>> d = Differ()
2025-07-02 06:41:19.038 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.038 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.038 >>> print(''.join(results), end="")
2025-07-02 06:41:19.038 - abcDefghiJkl
2025-07-02 06:41:19.038 + abcdefGhijkl
2025-07-02 06:41:19.039 """
2025-07-02 06:41:19.039
2025-07-02 06:41:19.039 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.039 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.039 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.039 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.039 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.039
2025-07-02 06:41:19.039 # search for the pair that matches best without being identical
2025-07-02 06:41:19.039 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.039 # on junk -- unless we have to)
2025-07-02 06:41:19.039 for j in range(blo, bhi):
2025-07-02 06:41:19.039 bj = b[j]
2025-07-02 06:41:19.039 cruncher.set_seq2(bj)
2025-07-02 06:41:19.039 for i in range(alo, ahi):
2025-07-02 06:41:19.039 ai = a[i]
2025-07-02 06:41:19.039 if ai == bj:
2025-07-02 06:41:19.039 if eqi is None:
2025-07-02 06:41:19.039 eqi, eqj = i, j
2025-07-02 06:41:19.039 continue
2025-07-02 06:41:19.039 cruncher.set_seq1(ai)
2025-07-02 06:41:19.040 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.040 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.040 # compares by a factor of 3.
2025-07-02 06:41:19.040 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.040 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.040 # of the computation is cached by cruncher
2025-07-02 06:41:19.040 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.040 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.040 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.040 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.040 if best_ratio < cutoff:
2025-07-02 06:41:19.040 # no non-identical "pretty close" pair
2025-07-02 06:41:19.040 if eqi is None:
2025-07-02 06:41:19.040 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.040 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.040 return
2025-07-02 06:41:19.040 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.040 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.040 else:
2025-07-02 06:41:19.040 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.041 eqi = None
2025-07-02 06:41:19.041
2025-07-02 06:41:19.041 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.041 # identical
2025-07-02 06:41:19.041
2025-07-02 06:41:19.041 # pump out diffs from before the synch point
2025-07-02 06:41:19.041 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.041
2025-07-02 06:41:19.041 # do intraline marking on the synch pair
2025-07-02 06:41:19.041 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.041 if eqi is None:
2025-07-02 06:41:19.041 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.041 atags = btags = ""
2025-07-02 06:41:19.041 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.041 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.041 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.041 if tag == 'replace':
2025-07-02 06:41:19.041 atags += '^' * la
2025-07-02 06:41:19.041 btags += '^' * lb
2025-07-02 06:41:19.042 elif tag == 'delete':
2025-07-02 06:41:19.042 atags += '-' * la
2025-07-02 06:41:19.042 elif tag == 'insert':
2025-07-02 06:41:19.042 btags += '+' * lb
2025-07-02 06:41:19.042 elif tag == 'equal':
2025-07-02 06:41:19.042 atags += ' ' * la
2025-07-02 06:41:19.042 btags += ' ' * lb
2025-07-02 06:41:19.042 else:
2025-07-02 06:41:19.042 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.042 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.042 else:
2025-07-02 06:41:19.042 # the synch pair is identical
2025-07-02 06:41:19.042 yield ' ' + aelt
2025-07-02 06:41:19.042
2025-07-02 06:41:19.042 # pump out diffs from after the synch point
2025-07-02 06:41:19.042 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.042
2025-07-02 06:41:19.042 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.042 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.042
2025-07-02 06:41:19.042 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.043 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.044 alo = 502, ahi = 1101
2025-07-02 06:41:19.044 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.044 blo = 502, bhi = 1101
2025-07-02 06:41:19.044
2025-07-02 06:41:19.044 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.044 g = []
2025-07-02 06:41:19.044 if alo < ahi:
2025-07-02 06:41:19.044 if blo < bhi:
2025-07-02 06:41:19.044 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.044 else:
2025-07-02 06:41:19.044 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.044 elif blo < bhi:
2025-07-02 06:41:19.044 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.044
2025-07-02 06:41:19.044 > yield from g
2025-07-02 06:41:19.044
2025-07-02 06:41:19.044 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.044 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.044
2025-07-02 06:41:19.045 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.045 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.045 alo = 502, ahi = 1101
2025-07-02 06:41:19.045 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.045 blo = 502, bhi = 1101
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.045 r"""
2025-07-02 06:41:19.045 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.045 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.045 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.045 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045 Example:
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045 >>> d = Differ()
2025-07-02 06:41:19.045 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.045 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.045 >>> print(''.join(results), end="")
2025-07-02 06:41:19.045 - abcDefghiJkl
2025-07-02 06:41:19.045 + abcdefGhijkl
2025-07-02 06:41:19.045 """
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.045 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.045 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.045 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.045 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045 # search for the pair that matches best without being identical
2025-07-02 06:41:19.045 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.045 # on junk -- unless we have to)
2025-07-02 06:41:19.045 for j in range(blo, bhi):
2025-07-02 06:41:19.045 bj = b[j]
2025-07-02 06:41:19.046 cruncher.set_seq2(bj)
2025-07-02 06:41:19.046 for i in range(alo, ahi):
2025-07-02 06:41:19.046 ai = a[i]
2025-07-02 06:41:19.046 if ai == bj:
2025-07-02 06:41:19.046 if eqi is None:
2025-07-02 06:41:19.046 eqi, eqj = i, j
2025-07-02 06:41:19.046 continue
2025-07-02 06:41:19.046 cruncher.set_seq1(ai)
2025-07-02 06:41:19.046 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.046 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.046 # compares by a factor of 3.
2025-07-02 06:41:19.046 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.046 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.046 # of the computation is cached by cruncher
2025-07-02 06:41:19.046 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.046 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.046 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.046 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.046 if best_ratio < cutoff:
2025-07-02 06:41:19.046 # no non-identical "pretty close" pair
2025-07-02 06:41:19.047 if eqi is None:
2025-07-02 06:41:19.047 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.047 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.047 return
2025-07-02 06:41:19.047 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.047 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.047 else:
2025-07-02 06:41:19.047 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.047 eqi = None
2025-07-02 06:41:19.047
2025-07-02 06:41:19.047 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.047 # identical
2025-07-02 06:41:19.047
2025-07-02 06:41:19.047 # pump out diffs from before the synch point
2025-07-02 06:41:19.047 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.047
2025-07-02 06:41:19.047 # do intraline marking on the synch pair
2025-07-02 06:41:19.047 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.047 if eqi is None:
2025-07-02 06:41:19.047 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.048 atags = btags = ""
2025-07-02 06:41:19.048 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.048 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.048 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.048 if tag == 'replace':
2025-07-02 06:41:19.048 atags += '^' * la
2025-07-02 06:41:19.048 btags += '^' * lb
2025-07-02 06:41:19.048 elif tag == 'delete':
2025-07-02 06:41:19.048 atags += '-' * la
2025-07-02 06:41:19.048 elif tag == 'insert':
2025-07-02 06:41:19.048 btags += '+' * lb
2025-07-02 06:41:19.048 elif tag == 'equal':
2025-07-02 06:41:19.048 atags += ' ' * la
2025-07-02 06:41:19.048 btags += ' ' * lb
2025-07-02 06:41:19.048 else:
2025-07-02 06:41:19.048 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.048 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.048 else:
2025-07-02 06:41:19.048 # the synch pair is identical
2025-07-02 06:41:19.048 yield ' ' + aelt
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049 # pump out diffs from after the synch point
2025-07-02 06:41:19.049 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.049 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.049 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.049 alo = 503, ahi = 1101
2025-07-02 06:41:19.049 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.049 blo = 503, bhi = 1101
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.049 g = []
2025-07-02 06:41:19.049 if alo < ahi:
2025-07-02 06:41:19.049 if blo < bhi:
2025-07-02 06:41:19.049 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.049 else:
2025-07-02 06:41:19.049 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.050 elif blo < bhi:
2025-07-02 06:41:19.050 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 > yield from g
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.050 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.050 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.050 alo = 503, ahi = 1101
2025-07-02 06:41:19.050 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.050 blo = 503, bhi = 1101
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.050 r"""
2025-07-02 06:41:19.050 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.050 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.050 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.050 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051 Example:
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051 >>> d = Differ()
2025-07-02 06:41:19.051 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.051 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.051 >>> print(''.join(results), end="")
2025-07-02 06:41:19.051 - abcDefghiJkl
2025-07-02 06:41:19.051 + abcdefGhijkl
2025-07-02 06:41:19.051 """
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.051 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.051 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.051 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.051 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051 # search for the pair that matches best without being identical
2025-07-02 06:41:19.051 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.052 # on junk -- unless we have to)
2025-07-02 06:41:19.052 for j in range(blo, bhi):
2025-07-02 06:41:19.052 bj = b[j]
2025-07-02 06:41:19.052 cruncher.set_seq2(bj)
2025-07-02 06:41:19.052 for i in range(alo, ahi):
2025-07-02 06:41:19.052 ai = a[i]
2025-07-02 06:41:19.052 if ai == bj:
2025-07-02 06:41:19.052 if eqi is None:
2025-07-02 06:41:19.052 eqi, eqj = i, j
2025-07-02 06:41:19.052 continue
2025-07-02 06:41:19.052 cruncher.set_seq1(ai)
2025-07-02 06:41:19.052 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.052 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.052 # compares by a factor of 3.
2025-07-02 06:41:19.052 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.052 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.052 # of the computation is cached by cruncher
2025-07-02 06:41:19.052 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.053 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.053 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.053 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.053 if best_ratio < cutoff:
2025-07-02 06:41:19.053 # no non-identical "pretty close" pair
2025-07-02 06:41:19.053 if eqi is None:
2025-07-02 06:41:19.053 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.053 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.053 return
2025-07-02 06:41:19.053 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.053 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.053 else:
2025-07-02 06:41:19.053 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.053 eqi = None
2025-07-02 06:41:19.053
2025-07-02 06:41:19.053 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.054 # identical
2025-07-02 06:41:19.054
2025-07-02 06:41:19.054 # pump out diffs from before the synch point
2025-07-02 06:41:19.054 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.054
2025-07-02 06:41:19.054 # do intraline marking on the synch pair
2025-07-02 06:41:19.054 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.054 if eqi is None:
2025-07-02 06:41:19.054 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.054 atags = btags = ""
2025-07-02 06:41:19.054 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.054 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.054 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.054 if tag == 'replace':
2025-07-02 06:41:19.054 atags += '^' * la
2025-07-02 06:41:19.054 btags += '^' * lb
2025-07-02 06:41:19.054 elif tag == 'delete':
2025-07-02 06:41:19.054 atags += '-' * la
2025-07-02 06:41:19.054 elif tag == 'insert':
2025-07-02 06:41:19.054 btags += '+' * lb
2025-07-02 06:41:19.055 elif tag == 'equal':
2025-07-02 06:41:19.055 atags += ' ' * la
2025-07-02 06:41:19.055 btags += ' ' * lb
2025-07-02 06:41:19.055 else:
2025-07-02 06:41:19.055 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.055 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.055 else:
2025-07-02 06:41:19.055 # the synch pair is identical
2025-07-02 06:41:19.055 yield ' ' + aelt
2025-07-02 06:41:19.055
2025-07-02 06:41:19.055 # pump out diffs from after the synch point
2025-07-02 06:41:19.055 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.055
2025-07-02 06:41:19.055 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.055 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.055
2025-07-02 06:41:19.055 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.055 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.055 alo = 504, ahi = 1101
2025-07-02 06:41:19.056 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.056 blo = 504, bhi = 1101
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.056 g = []
2025-07-02 06:41:19.056 if alo < ahi:
2025-07-02 06:41:19.056 if blo < bhi:
2025-07-02 06:41:19.056 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.056 else:
2025-07-02 06:41:19.056 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.056 elif blo < bhi:
2025-07-02 06:41:19.056 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 > yield from g
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.056 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.056 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.057 alo = 504, ahi = 1101
2025-07-02 06:41:19.057 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.057 blo = 504, bhi = 1101
2025-07-02 06:41:19.057
2025-07-02 06:41:19.057 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.057 r"""
2025-07-02 06:41:19.057 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.057 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.057 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.057 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.057
2025-07-02 06:41:19.057 Example:
2025-07-02 06:41:19.057
2025-07-02 06:41:19.057 >>> d = Differ()
2025-07-02 06:41:19.057 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.057 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.057 >>> print(''.join(results), end="")
2025-07-02 06:41:19.057 - abcDefghiJkl
2025-07-02 06:41:19.058 + abcdefGhijkl
2025-07-02 06:41:19.058 """
2025-07-02 06:41:19.058
2025-07-02 06:41:19.058 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.058 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.058 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.058 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.058 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.058
2025-07-02 06:41:19.058 # search for the pair that matches best without being identical
2025-07-02 06:41:19.058 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.058 # on junk -- unless we have to)
2025-07-02 06:41:19.058 for j in range(blo, bhi):
2025-07-02 06:41:19.058 bj = b[j]
2025-07-02 06:41:19.058 cruncher.set_seq2(bj)
2025-07-02 06:41:19.058 for i in range(alo, ahi):
2025-07-02 06:41:19.058 ai = a[i]
2025-07-02 06:41:19.058 if ai == bj:
2025-07-02 06:41:19.059 if eqi is None:
2025-07-02 06:41:19.059 eqi, eqj = i, j
2025-07-02 06:41:19.059 continue
2025-07-02 06:41:19.059 cruncher.set_seq1(ai)
2025-07-02 06:41:19.059 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.059 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.059 # compares by a factor of 3.
2025-07-02 06:41:19.059 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.059 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.059 # of the computation is cached by cruncher
2025-07-02 06:41:19.059 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.059 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.059 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.059 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.059 if best_ratio < cutoff:
2025-07-02 06:41:19.059 # no non-identical "pretty close" pair
2025-07-02 06:41:19.059 if eqi is None:
2025-07-02 06:41:19.059 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.060 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.060 return
2025-07-02 06:41:19.060 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.060 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.060 else:
2025-07-02 06:41:19.060 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.060 eqi = None
2025-07-02 06:41:19.060
2025-07-02 06:41:19.060 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.060 # identical
2025-07-02 06:41:19.060
2025-07-02 06:41:19.060 # pump out diffs from before the synch point
2025-07-02 06:41:19.060 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.060
2025-07-02 06:41:19.060 # do intraline marking on the synch pair
2025-07-02 06:41:19.060 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.060 if eqi is None:
2025-07-02 06:41:19.060 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.061 atags = btags = ""
2025-07-02 06:41:19.061 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.061 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.061 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.061 if tag == 'replace':
2025-07-02 06:41:19.061 atags += '^' * la
2025-07-02 06:41:19.061 btags += '^' * lb
2025-07-02 06:41:19.061 elif tag == 'delete':
2025-07-02 06:41:19.061 atags += '-' * la
2025-07-02 06:41:19.061 elif tag == 'insert':
2025-07-02 06:41:19.061 btags += '+' * lb
2025-07-02 06:41:19.061 elif tag == 'equal':
2025-07-02 06:41:19.061 atags += ' ' * la
2025-07-02 06:41:19.061 btags += ' ' * lb
2025-07-02 06:41:19.061 else:
2025-07-02 06:41:19.061 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.061 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.061 else:
2025-07-02 06:41:19.061 # the synch pair is identical
2025-07-02 06:41:19.062 yield ' ' + aelt
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062 # pump out diffs from after the synch point
2025-07-02 06:41:19.062 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.062 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.062 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.062 alo = 505, ahi = 1101
2025-07-02 06:41:19.062 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.062 blo = 505, bhi = 1101
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.062 g = []
2025-07-02 06:41:19.062 if alo < ahi:
2025-07-02 06:41:19.062 if blo < bhi:
2025-07-02 06:41:19.063 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.063 else:
2025-07-02 06:41:19.063 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.063 elif blo < bhi:
2025-07-02 06:41:19.063 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 > yield from g
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.063 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.063 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.063 alo = 505, ahi = 1101
2025-07-02 06:41:19.063 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.063 blo = 505, bhi = 1101
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.063 r"""
2025-07-02 06:41:19.064 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.064 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.064 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.064 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.064
2025-07-02 06:41:19.064 Example:
2025-07-02 06:41:19.064
2025-07-02 06:41:19.064 >>> d = Differ()
2025-07-02 06:41:19.064 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.064 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.064 >>> print(''.join(results), end="")
2025-07-02 06:41:19.064 - abcDefghiJkl
2025-07-02 06:41:19.064 + abcdefGhijkl
2025-07-02 06:41:19.064 """
2025-07-02 06:41:19.064
2025-07-02 06:41:19.064 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.064 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.064 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.064 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.065 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.065
2025-07-02 06:41:19.065 # search for the pair that matches best without being identical
2025-07-02 06:41:19.065 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.065 # on junk -- unless we have to)
2025-07-02 06:41:19.065 for j in range(blo, bhi):
2025-07-02 06:41:19.065 bj = b[j]
2025-07-02 06:41:19.065 cruncher.set_seq2(bj)
2025-07-02 06:41:19.065 for i in range(alo, ahi):
2025-07-02 06:41:19.065 ai = a[i]
2025-07-02 06:41:19.065 if ai == bj:
2025-07-02 06:41:19.065 if eqi is None:
2025-07-02 06:41:19.065 eqi, eqj = i, j
2025-07-02 06:41:19.065 continue
2025-07-02 06:41:19.065 cruncher.set_seq1(ai)
2025-07-02 06:41:19.065 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.065 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.065 # compares by a factor of 3.
2025-07-02 06:41:19.065 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.065 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.066 # of the computation is cached by cruncher
2025-07-02 06:41:19.066 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.066 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.066 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.066 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.066 if best_ratio < cutoff:
2025-07-02 06:41:19.066 # no non-identical "pretty close" pair
2025-07-02 06:41:19.066 if eqi is None:
2025-07-02 06:41:19.066 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.066 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.066 return
2025-07-02 06:41:19.066 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.066 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.066 else:
2025-07-02 06:41:19.066 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.066 eqi = None
2025-07-02 06:41:19.066
2025-07-02 06:41:19.066 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.066 # identical
2025-07-02 06:41:19.066
2025-07-02 06:41:19.067 # pump out diffs from before the synch point
2025-07-02 06:41:19.067 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.067
2025-07-02 06:41:19.067 # do intraline marking on the synch pair
2025-07-02 06:41:19.067 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.067 if eqi is None:
2025-07-02 06:41:19.067 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.067 atags = btags = ""
2025-07-02 06:41:19.067 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.067 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.067 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.067 if tag == 'replace':
2025-07-02 06:41:19.067 atags += '^' * la
2025-07-02 06:41:19.067 btags += '^' * lb
2025-07-02 06:41:19.067 elif tag == 'delete':
2025-07-02 06:41:19.067 atags += '-' * la
2025-07-02 06:41:19.067 elif tag == 'insert':
2025-07-02 06:41:19.067 btags += '+' * lb
2025-07-02 06:41:19.067 elif tag == 'equal':
2025-07-02 06:41:19.067 atags += ' ' * la
2025-07-02 06:41:19.067 btags += ' ' * lb
2025-07-02 06:41:19.068 else:
2025-07-02 06:41:19.068 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.068 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.068 else:
2025-07-02 06:41:19.068 # the synch pair is identical
2025-07-02 06:41:19.068 yield ' ' + aelt
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068 # pump out diffs from after the synch point
2025-07-02 06:41:19.068 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.068 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.068 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.068 alo = 506, ahi = 1101
2025-07-02 06:41:19.068 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.068 blo = 506, bhi = 1101
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.069 g = []
2025-07-02 06:41:19.069 if alo < ahi:
2025-07-02 06:41:19.069 if blo < bhi:
2025-07-02 06:41:19.069 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.069 else:
2025-07-02 06:41:19.069 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.069 elif blo < bhi:
2025-07-02 06:41:19.069 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.069
2025-07-02 06:41:19.069 > yield from g
2025-07-02 06:41:19.069
2025-07-02 06:41:19.069 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.069 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.069
2025-07-02 06:41:19.069 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.069 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.069 alo = 506, ahi = 1101
2025-07-02 06:41:19.070 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.070 blo = 506, bhi = 1101
2025-07-02 06:41:19.070
2025-07-02 06:41:19.070 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.070 r"""
2025-07-02 06:41:19.070 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.070 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.070 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.070 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.070
2025-07-02 06:41:19.070 Example:
2025-07-02 06:41:19.070
2025-07-02 06:41:19.070 >>> d = Differ()
2025-07-02 06:41:19.070 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.070 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.070 >>> print(''.join(results), end="")
2025-07-02 06:41:19.070 - abcDefghiJkl
2025-07-02 06:41:19.071 + abcdefGhijkl
2025-07-02 06:41:19.071 """
2025-07-02 06:41:19.071
2025-07-02 06:41:19.071 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.071 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.071 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.071 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.071 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.071
2025-07-02 06:41:19.071 # search for the pair that matches best without being identical
2025-07-02 06:41:19.071 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.071 # on junk -- unless we have to)
2025-07-02 06:41:19.071 for j in range(blo, bhi):
2025-07-02 06:41:19.071 bj = b[j]
2025-07-02 06:41:19.071 cruncher.set_seq2(bj)
2025-07-02 06:41:19.071 for i in range(alo, ahi):
2025-07-02 06:41:19.071 ai = a[i]
2025-07-02 06:41:19.071 if ai == bj:
2025-07-02 06:41:19.072 if eqi is None:
2025-07-02 06:41:19.072 eqi, eqj = i, j
2025-07-02 06:41:19.072 continue
2025-07-02 06:41:19.072 cruncher.set_seq1(ai)
2025-07-02 06:41:19.072 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.072 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.072 # compares by a factor of 3.
2025-07-02 06:41:19.072 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.072 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.072 # of the computation is cached by cruncher
2025-07-02 06:41:19.072 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.072 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.072 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.072 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.072 if best_ratio < cutoff:
2025-07-02 06:41:19.072 # no non-identical "pretty close" pair
2025-07-02 06:41:19.072 if eqi is None:
2025-07-02 06:41:19.072 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.072 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.073 return
2025-07-02 06:41:19.073 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.073 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.073 else:
2025-07-02 06:41:19.073 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.073 eqi = None
2025-07-02 06:41:19.073
2025-07-02 06:41:19.073 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.073 # identical
2025-07-02 06:41:19.073
2025-07-02 06:41:19.073 # pump out diffs from before the synch point
2025-07-02 06:41:19.073 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.073
2025-07-02 06:41:19.073 # do intraline marking on the synch pair
2025-07-02 06:41:19.073 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.073 if eqi is None:
2025-07-02 06:41:19.073 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.073 atags = btags = ""
2025-07-02 06:41:19.073 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.073 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.074 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.074 if tag == 'replace':
2025-07-02 06:41:19.074 atags += '^' * la
2025-07-02 06:41:19.074 btags += '^' * lb
2025-07-02 06:41:19.074 elif tag == 'delete':
2025-07-02 06:41:19.074 atags += '-' * la
2025-07-02 06:41:19.074 elif tag == 'insert':
2025-07-02 06:41:19.074 btags += '+' * lb
2025-07-02 06:41:19.074 elif tag == 'equal':
2025-07-02 06:41:19.074 atags += ' ' * la
2025-07-02 06:41:19.074 btags += ' ' * lb
2025-07-02 06:41:19.074 else:
2025-07-02 06:41:19.074 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.074 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.074 else:
2025-07-02 06:41:19.074 # the synch pair is identical
2025-07-02 06:41:19.074 yield ' ' + aelt
2025-07-02 06:41:19.074
2025-07-02 06:41:19.074 # pump out diffs from after the synch point
2025-07-02 06:41:19.074 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.074
2025-07-02 06:41:19.075 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.075 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.075
2025-07-02 06:41:19.075 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.075 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.075 alo = 507, ahi = 1101
2025-07-02 06:41:19.075 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.075 blo = 507, bhi = 1101
2025-07-02 06:41:19.075
2025-07-02 06:41:19.075 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.075 g = []
2025-07-02 06:41:19.075 if alo < ahi:
2025-07-02 06:41:19.075 if blo < bhi:
2025-07-02 06:41:19.075 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.075 else:
2025-07-02 06:41:19.075 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.075 elif blo < bhi:
2025-07-02 06:41:19.075 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.075
2025-07-02 06:41:19.075 > yield from g
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.076 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.076 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.076 alo = 507, ahi = 1101
2025-07-02 06:41:19.076 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.076 blo = 507, bhi = 1101
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.076 r"""
2025-07-02 06:41:19.076 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.076 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.076 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.076 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 Example:
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 >>> d = Differ()
2025-07-02 06:41:19.077 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.077 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.077 >>> print(''.join(results), end="")
2025-07-02 06:41:19.077 - abcDefghiJkl
2025-07-02 06:41:19.077 + abcdefGhijkl
2025-07-02 06:41:19.077 """
2025-07-02 06:41:19.077
2025-07-02 06:41:19.077 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.077 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.077 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.077 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.077 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.077
2025-07-02 06:41:19.077 # search for the pair that matches best without being identical
2025-07-02 06:41:19.077 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.077 # on junk -- unless we have to)
2025-07-02 06:41:19.077 for j in range(blo, bhi):
2025-07-02 06:41:19.077 bj = b[j]
2025-07-02 06:41:19.077 cruncher.set_seq2(bj)
2025-07-02 06:41:19.078 for i in range(alo, ahi):
2025-07-02 06:41:19.078 ai = a[i]
2025-07-02 06:41:19.078 if ai == bj:
2025-07-02 06:41:19.078 if eqi is None:
2025-07-02 06:41:19.078 eqi, eqj = i, j
2025-07-02 06:41:19.078 continue
2025-07-02 06:41:19.078 cruncher.set_seq1(ai)
2025-07-02 06:41:19.078 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.078 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.078 # compares by a factor of 3.
2025-07-02 06:41:19.078 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.078 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.078 # of the computation is cached by cruncher
2025-07-02 06:41:19.078 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.078 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.078 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.078 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.078 if best_ratio < cutoff:
2025-07-02 06:41:19.078 # no non-identical "pretty close" pair
2025-07-02 06:41:19.078 if eqi is None:
2025-07-02 06:41:19.079 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.079 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.079 return
2025-07-02 06:41:19.079 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.079 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.079 else:
2025-07-02 06:41:19.079 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.079 eqi = None
2025-07-02 06:41:19.079
2025-07-02 06:41:19.079 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.079 # identical
2025-07-02 06:41:19.079
2025-07-02 06:41:19.079 # pump out diffs from before the synch point
2025-07-02 06:41:19.079 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.079
2025-07-02 06:41:19.079 # do intraline marking on the synch pair
2025-07-02 06:41:19.079 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.079 if eqi is None:
2025-07-02 06:41:19.080 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.080 atags = btags = ""
2025-07-02 06:41:19.080 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.080 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.080 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.080 if tag == 'replace':
2025-07-02 06:41:19.080 atags += '^' * la
2025-07-02 06:41:19.080 btags += '^' * lb
2025-07-02 06:41:19.080 elif tag == 'delete':
2025-07-02 06:41:19.080 atags += '-' * la
2025-07-02 06:41:19.080 elif tag == 'insert':
2025-07-02 06:41:19.080 btags += '+' * lb
2025-07-02 06:41:19.080 elif tag == 'equal':
2025-07-02 06:41:19.080 atags += ' ' * la
2025-07-02 06:41:19.080 btags += ' ' * lb
2025-07-02 06:41:19.080 else:
2025-07-02 06:41:19.080 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.080 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.080 else:
2025-07-02 06:41:19.080 # the synch pair is identical
2025-07-02 06:41:19.081 yield ' ' + aelt
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081 # pump out diffs from after the synch point
2025-07-02 06:41:19.081 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.081 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.081 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.081 alo = 510, ahi = 1101
2025-07-02 06:41:19.081 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.081 blo = 510, bhi = 1101
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.081 g = []
2025-07-02 06:41:19.081 if alo < ahi:
2025-07-02 06:41:19.081 if blo < bhi:
2025-07-02 06:41:19.081 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.082 else:
2025-07-02 06:41:19.082 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.082 elif blo < bhi:
2025-07-02 06:41:19.082 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 > yield from g
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.082 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.082 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.082 alo = 510, ahi = 1101
2025-07-02 06:41:19.082 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.082 blo = 510, bhi = 1101
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.082 r"""
2025-07-02 06:41:19.082 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.082 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.083 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.083 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.083
2025-07-02 06:41:19.083 Example:
2025-07-02 06:41:19.083
2025-07-02 06:41:19.083 >>> d = Differ()
2025-07-02 06:41:19.083 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.083 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.083 >>> print(''.join(results), end="")
2025-07-02 06:41:19.083 - abcDefghiJkl
2025-07-02 06:41:19.083 + abcdefGhijkl
2025-07-02 06:41:19.083 """
2025-07-02 06:41:19.083
2025-07-02 06:41:19.083 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.083 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.083 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.083 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.083 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.083
2025-07-02 06:41:19.084 # search for the pair that matches best without being identical
2025-07-02 06:41:19.084 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.084 # on junk -- unless we have to)
2025-07-02 06:41:19.084 for j in range(blo, bhi):
2025-07-02 06:41:19.084 bj = b[j]
2025-07-02 06:41:19.084 cruncher.set_seq2(bj)
2025-07-02 06:41:19.084 for i in range(alo, ahi):
2025-07-02 06:41:19.084 ai = a[i]
2025-07-02 06:41:19.084 if ai == bj:
2025-07-02 06:41:19.084 if eqi is None:
2025-07-02 06:41:19.084 eqi, eqj = i, j
2025-07-02 06:41:19.084 continue
2025-07-02 06:41:19.084 cruncher.set_seq1(ai)
2025-07-02 06:41:19.084 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.084 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.084 # compares by a factor of 3.
2025-07-02 06:41:19.084 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.084 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.084 # of the computation is cached by cruncher
2025-07-02 06:41:19.085 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.085 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.085 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.085 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.085 if best_ratio < cutoff:
2025-07-02 06:41:19.085 # no non-identical "pretty close" pair
2025-07-02 06:41:19.085 if eqi is None:
2025-07-02 06:41:19.085 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.085 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.085 return
2025-07-02 06:41:19.085 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.085 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.085 else:
2025-07-02 06:41:19.085 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.085 eqi = None
2025-07-02 06:41:19.085
2025-07-02 06:41:19.085 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.085 # identical
2025-07-02 06:41:19.085
2025-07-02 06:41:19.085 # pump out diffs from before the synch point
2025-07-02 06:41:19.086 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.086
2025-07-02 06:41:19.086 # do intraline marking on the synch pair
2025-07-02 06:41:19.086 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.086 if eqi is None:
2025-07-02 06:41:19.086 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.086 atags = btags = ""
2025-07-02 06:41:19.086 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.086 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.086 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.086 if tag == 'replace':
2025-07-02 06:41:19.086 atags += '^' * la
2025-07-02 06:41:19.086 btags += '^' * lb
2025-07-02 06:41:19.086 elif tag == 'delete':
2025-07-02 06:41:19.086 atags += '-' * la
2025-07-02 06:41:19.086 elif tag == 'insert':
2025-07-02 06:41:19.086 btags += '+' * lb
2025-07-02 06:41:19.086 elif tag == 'equal':
2025-07-02 06:41:19.086 atags += ' ' * la
2025-07-02 06:41:19.087 btags += ' ' * lb
2025-07-02 06:41:19.087 else:
2025-07-02 06:41:19.087 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.087 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.087 else:
2025-07-02 06:41:19.087 # the synch pair is identical
2025-07-02 06:41:19.087 yield ' ' + aelt
2025-07-02 06:41:19.087
2025-07-02 06:41:19.087 # pump out diffs from after the synch point
2025-07-02 06:41:19.087 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.087
2025-07-02 06:41:19.087 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.087 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.087
2025-07-02 06:41:19.087 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.087 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.087 alo = 511, ahi = 1101
2025-07-02 06:41:19.087 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.087 blo = 511, bhi = 1101
2025-07-02 06:41:19.087
2025-07-02 06:41:19.088 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.088 g = []
2025-07-02 06:41:19.088 if alo < ahi:
2025-07-02 06:41:19.088 if blo < bhi:
2025-07-02 06:41:19.088 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.088 else:
2025-07-02 06:41:19.088 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.088 elif blo < bhi:
2025-07-02 06:41:19.088 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.088
2025-07-02 06:41:19.088 > yield from g
2025-07-02 06:41:19.088
2025-07-02 06:41:19.088 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.088 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.088
2025-07-02 06:41:19.088 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.088 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.088 alo = 511, ahi = 1101
2025-07-02 06:41:19.088 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.089 blo = 511, bhi = 1101
2025-07-02 06:41:19.089
2025-07-02 06:41:19.089 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.089 r"""
2025-07-02 06:41:19.089 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.089 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.089 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.089 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.089
2025-07-02 06:41:19.089 Example:
2025-07-02 06:41:19.089
2025-07-02 06:41:19.089 >>> d = Differ()
2025-07-02 06:41:19.089 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.089 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.089 >>> print(''.join(results), end="")
2025-07-02 06:41:19.089 - abcDefghiJkl
2025-07-02 06:41:19.090 + abcdefGhijkl
2025-07-02 06:41:19.090 """
2025-07-02 06:41:19.090
2025-07-02 06:41:19.090 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.090 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.090 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.090 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.090 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.090
2025-07-02 06:41:19.090 # search for the pair that matches best without being identical
2025-07-02 06:41:19.090 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.090 # on junk -- unless we have to)
2025-07-02 06:41:19.090 for j in range(blo, bhi):
2025-07-02 06:41:19.090 bj = b[j]
2025-07-02 06:41:19.090 cruncher.set_seq2(bj)
2025-07-02 06:41:19.090 for i in range(alo, ahi):
2025-07-02 06:41:19.090 ai = a[i]
2025-07-02 06:41:19.090 if ai == bj:
2025-07-02 06:41:19.091 if eqi is None:
2025-07-02 06:41:19.091 eqi, eqj = i, j
2025-07-02 06:41:19.091 continue
2025-07-02 06:41:19.091 cruncher.set_seq1(ai)
2025-07-02 06:41:19.091 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.091 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.091 # compares by a factor of 3.
2025-07-02 06:41:19.091 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.091 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.091 # of the computation is cached by cruncher
2025-07-02 06:41:19.091 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.091 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.091 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.091 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.091 if best_ratio < cutoff:
2025-07-02 06:41:19.091 # no non-identical "pretty close" pair
2025-07-02 06:41:19.091 if eqi is None:
2025-07-02 06:41:19.091 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.091 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.091 return
2025-07-02 06:41:19.092 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.092 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.092 else:
2025-07-02 06:41:19.092 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.092 eqi = None
2025-07-02 06:41:19.092
2025-07-02 06:41:19.092 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.092 # identical
2025-07-02 06:41:19.092
2025-07-02 06:41:19.092 # pump out diffs from before the synch point
2025-07-02 06:41:19.092 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.092
2025-07-02 06:41:19.092 # do intraline marking on the synch pair
2025-07-02 06:41:19.092 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.092 if eqi is None:
2025-07-02 06:41:19.092 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.092 atags = btags = ""
2025-07-02 06:41:19.092 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.092 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.092 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.093 if tag == 'replace':
2025-07-02 06:41:19.093 atags += '^' * la
2025-07-02 06:41:19.093 btags += '^' * lb
2025-07-02 06:41:19.093 elif tag == 'delete':
2025-07-02 06:41:19.093 atags += '-' * la
2025-07-02 06:41:19.093 elif tag == 'insert':
2025-07-02 06:41:19.093 btags += '+' * lb
2025-07-02 06:41:19.093 elif tag == 'equal':
2025-07-02 06:41:19.093 atags += ' ' * la
2025-07-02 06:41:19.093 btags += ' ' * lb
2025-07-02 06:41:19.093 else:
2025-07-02 06:41:19.093 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.093 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.093 else:
2025-07-02 06:41:19.093 # the synch pair is identical
2025-07-02 06:41:19.093 yield ' ' + aelt
2025-07-02 06:41:19.093
2025-07-02 06:41:19.093 # pump out diffs from after the synch point
2025-07-02 06:41:19.093 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.093
2025-07-02 06:41:19.093 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.094 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.094
2025-07-02 06:41:19.094 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.094 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.094 alo = 512, ahi = 1101
2025-07-02 06:41:19.094 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.094 blo = 512, bhi = 1101
2025-07-02 06:41:19.094
2025-07-02 06:41:19.094 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.094 g = []
2025-07-02 06:41:19.094 if alo < ahi:
2025-07-02 06:41:19.094 if blo < bhi:
2025-07-02 06:41:19.094 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.094 else:
2025-07-02 06:41:19.094 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.094 elif blo < bhi:
2025-07-02 06:41:19.094 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.094
2025-07-02 06:41:19.094 > yield from g
2025-07-02 06:41:19.094
2025-07-02 06:41:19.095 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.095 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.095 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.095 alo = 512, ahi = 1101
2025-07-02 06:41:19.095 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.095 blo = 512, bhi = 1101
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.095 r"""
2025-07-02 06:41:19.095 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.095 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.095 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.095 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095 Example:
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095 >>> d = Differ()
2025-07-02 06:41:19.095 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.096 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.096 >>> print(''.join(results), end="")
2025-07-02 06:41:19.096 - abcDefghiJkl
2025-07-02 06:41:19.096 + abcdefGhijkl
2025-07-02 06:41:19.096 """
2025-07-02 06:41:19.096
2025-07-02 06:41:19.096 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.096 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.096 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.096 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.096 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.096
2025-07-02 06:41:19.096 # search for the pair that matches best without being identical
2025-07-02 06:41:19.096 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.096 # on junk -- unless we have to)
2025-07-02 06:41:19.096 for j in range(blo, bhi):
2025-07-02 06:41:19.096 bj = b[j]
2025-07-02 06:41:19.096 cruncher.set_seq2(bj)
2025-07-02 06:41:19.097 for i in range(alo, ahi):
2025-07-02 06:41:19.097 ai = a[i]
2025-07-02 06:41:19.097 if ai == bj:
2025-07-02 06:41:19.097 if eqi is None:
2025-07-02 06:41:19.097 eqi, eqj = i, j
2025-07-02 06:41:19.097 continue
2025-07-02 06:41:19.097 cruncher.set_seq1(ai)
2025-07-02 06:41:19.097 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.097 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.097 # compares by a factor of 3.
2025-07-02 06:41:19.097 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.097 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.097 # of the computation is cached by cruncher
2025-07-02 06:41:19.097 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.097 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.097 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.097 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.097 if best_ratio < cutoff:
2025-07-02 06:41:19.097 # no non-identical "pretty close" pair
2025-07-02 06:41:19.098 if eqi is None:
2025-07-02 06:41:19.098 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.098 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.098 return
2025-07-02 06:41:19.098 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.098 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.098 else:
2025-07-02 06:41:19.098 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.098 eqi = None
2025-07-02 06:41:19.098
2025-07-02 06:41:19.098 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.098 # identical
2025-07-02 06:41:19.098
2025-07-02 06:41:19.098 # pump out diffs from before the synch point
2025-07-02 06:41:19.098 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.098
2025-07-02 06:41:19.098 # do intraline marking on the synch pair
2025-07-02 06:41:19.098 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.098 if eqi is None:
2025-07-02 06:41:19.099 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.099 atags = btags = ""
2025-07-02 06:41:19.099 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.099 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.099 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.099 if tag == 'replace':
2025-07-02 06:41:19.099 atags += '^' * la
2025-07-02 06:41:19.099 btags += '^' * lb
2025-07-02 06:41:19.099 elif tag == 'delete':
2025-07-02 06:41:19.099 atags += '-' * la
2025-07-02 06:41:19.099 elif tag == 'insert':
2025-07-02 06:41:19.099 btags += '+' * lb
2025-07-02 06:41:19.099 elif tag == 'equal':
2025-07-02 06:41:19.099 atags += ' ' * la
2025-07-02 06:41:19.099 btags += ' ' * lb
2025-07-02 06:41:19.099 else:
2025-07-02 06:41:19.099 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.099 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.099 else:
2025-07-02 06:41:19.099 # the synch pair is identical
2025-07-02 06:41:19.099 yield ' ' + aelt
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100 # pump out diffs from after the synch point
2025-07-02 06:41:19.100 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.100 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.100 alo = 513, ahi = 1101
2025-07-02 06:41:19.100 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.100 blo = 513, bhi = 1101
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.100 g = []
2025-07-02 06:41:19.100 if alo < ahi:
2025-07-02 06:41:19.100 if blo < bhi:
2025-07-02 06:41:19.100 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.101 else:
2025-07-02 06:41:19.101 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.101 elif blo < bhi:
2025-07-02 06:41:19.101 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 > yield from g
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.101 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.101 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.101 alo = 513, ahi = 1101
2025-07-02 06:41:19.101 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.101 blo = 513, bhi = 1101
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.101 r"""
2025-07-02 06:41:19.101 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.102 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.102 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.102 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.102
2025-07-02 06:41:19.102 Example:
2025-07-02 06:41:19.102
2025-07-02 06:41:19.102 >>> d = Differ()
2025-07-02 06:41:19.102 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.102 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.102 >>> print(''.join(results), end="")
2025-07-02 06:41:19.102 - abcDefghiJkl
2025-07-02 06:41:19.102 + abcdefGhijkl
2025-07-02 06:41:19.102 """
2025-07-02 06:41:19.102
2025-07-02 06:41:19.102 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.102 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.102 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.102 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.103 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.103
2025-07-02 06:41:19.103 # search for the pair that matches best without being identical
2025-07-02 06:41:19.103 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.103 # on junk -- unless we have to)
2025-07-02 06:41:19.103 for j in range(blo, bhi):
2025-07-02 06:41:19.103 bj = b[j]
2025-07-02 06:41:19.103 cruncher.set_seq2(bj)
2025-07-02 06:41:19.103 for i in range(alo, ahi):
2025-07-02 06:41:19.103 ai = a[i]
2025-07-02 06:41:19.103 if ai == bj:
2025-07-02 06:41:19.103 if eqi is None:
2025-07-02 06:41:19.103 eqi, eqj = i, j
2025-07-02 06:41:19.103 continue
2025-07-02 06:41:19.103 cruncher.set_seq1(ai)
2025-07-02 06:41:19.103 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.103 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.103 # compares by a factor of 3.
2025-07-02 06:41:19.103 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.103 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.104 # of the computation is cached by cruncher
2025-07-02 06:41:19.104 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.104 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.104 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.104 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.104 if best_ratio < cutoff:
2025-07-02 06:41:19.104 # no non-identical "pretty close" pair
2025-07-02 06:41:19.104 if eqi is None:
2025-07-02 06:41:19.104 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.104 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.104 return
2025-07-02 06:41:19.104 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.104 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.104 else:
2025-07-02 06:41:19.104 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.104 eqi = None
2025-07-02 06:41:19.104
2025-07-02 06:41:19.104 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.104 # identical
2025-07-02 06:41:19.104
2025-07-02 06:41:19.104 # pump out diffs from before the synch point
2025-07-02 06:41:19.105 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.105
2025-07-02 06:41:19.105 # do intraline marking on the synch pair
2025-07-02 06:41:19.105 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.105 if eqi is None:
2025-07-02 06:41:19.105 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.105 atags = btags = ""
2025-07-02 06:41:19.105 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.105 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.105 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.105 if tag == 'replace':
2025-07-02 06:41:19.105 atags += '^' * la
2025-07-02 06:41:19.105 btags += '^' * lb
2025-07-02 06:41:19.105 elif tag == 'delete':
2025-07-02 06:41:19.105 atags += '-' * la
2025-07-02 06:41:19.105 elif tag == 'insert':
2025-07-02 06:41:19.105 btags += '+' * lb
2025-07-02 06:41:19.105 elif tag == 'equal':
2025-07-02 06:41:19.106 atags += ' ' * la
2025-07-02 06:41:19.106 btags += ' ' * lb
2025-07-02 06:41:19.106 else:
2025-07-02 06:41:19.106 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.106 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.106 else:
2025-07-02 06:41:19.106 # the synch pair is identical
2025-07-02 06:41:19.106 yield ' ' + aelt
2025-07-02 06:41:19.106
2025-07-02 06:41:19.106 # pump out diffs from after the synch point
2025-07-02 06:41:19.106 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.106
2025-07-02 06:41:19.106 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.106 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.106
2025-07-02 06:41:19.106 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.106 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.106 alo = 514, ahi = 1101
2025-07-02 06:41:19.106 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.107 blo = 514, bhi = 1101
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.107 g = []
2025-07-02 06:41:19.107 if alo < ahi:
2025-07-02 06:41:19.107 if blo < bhi:
2025-07-02 06:41:19.107 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.107 else:
2025-07-02 06:41:19.107 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.107 elif blo < bhi:
2025-07-02 06:41:19.107 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 > yield from g
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.107 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.107 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.108 alo = 514, ahi = 1101
2025-07-02 06:41:19.108 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.108 blo = 514, bhi = 1101
2025-07-02 06:41:19.108
2025-07-02 06:41:19.108 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.108 r"""
2025-07-02 06:41:19.108 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.108 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.108 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.108 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.108
2025-07-02 06:41:19.108 Example:
2025-07-02 06:41:19.108
2025-07-02 06:41:19.108 >>> d = Differ()
2025-07-02 06:41:19.108 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.108 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.108 >>> print(''.join(results), end="")
2025-07-02 06:41:19.108 - abcDefghiJkl
2025-07-02 06:41:19.108 + abcdefGhijkl
2025-07-02 06:41:19.109 """
2025-07-02 06:41:19.109
2025-07-02 06:41:19.109 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.109 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.109 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.109 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.109 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.109
2025-07-02 06:41:19.109 # search for the pair that matches best without being identical
2025-07-02 06:41:19.109 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.109 # on junk -- unless we have to)
2025-07-02 06:41:19.109 for j in range(blo, bhi):
2025-07-02 06:41:19.109 bj = b[j]
2025-07-02 06:41:19.109 cruncher.set_seq2(bj)
2025-07-02 06:41:19.109 for i in range(alo, ahi):
2025-07-02 06:41:19.109 ai = a[i]
2025-07-02 06:41:19.109 if ai == bj:
2025-07-02 06:41:19.109 if eqi is None:
2025-07-02 06:41:19.109 eqi, eqj = i, j
2025-07-02 06:41:19.109 continue
2025-07-02 06:41:19.110 cruncher.set_seq1(ai)
2025-07-02 06:41:19.110 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.110 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.110 # compares by a factor of 3.
2025-07-02 06:41:19.110 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.110 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.110 # of the computation is cached by cruncher
2025-07-02 06:41:19.110 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.110 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.110 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.110 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.110 if best_ratio < cutoff:
2025-07-02 06:41:19.110 # no non-identical "pretty close" pair
2025-07-02 06:41:19.110 if eqi is None:
2025-07-02 06:41:19.110 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.110 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.110 return
2025-07-02 06:41:19.110 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.110 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.110 else:
2025-07-02 06:41:19.111 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.111 eqi = None
2025-07-02 06:41:19.111
2025-07-02 06:41:19.111 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.111 # identical
2025-07-02 06:41:19.111
2025-07-02 06:41:19.111 # pump out diffs from before the synch point
2025-07-02 06:41:19.111 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.111
2025-07-02 06:41:19.111 # do intraline marking on the synch pair
2025-07-02 06:41:19.111 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.111 if eqi is None:
2025-07-02 06:41:19.111 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.111 atags = btags = ""
2025-07-02 06:41:19.111 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.111 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.111 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.111 if tag == 'replace':
2025-07-02 06:41:19.111 atags += '^' * la
2025-07-02 06:41:19.111 btags += '^' * lb
2025-07-02 06:41:19.112 elif tag == 'delete':
2025-07-02 06:41:19.112 atags += '-' * la
2025-07-02 06:41:19.112 elif tag == 'insert':
2025-07-02 06:41:19.112 btags += '+' * lb
2025-07-02 06:41:19.112 elif tag == 'equal':
2025-07-02 06:41:19.112 atags += ' ' * la
2025-07-02 06:41:19.112 btags += ' ' * lb
2025-07-02 06:41:19.112 else:
2025-07-02 06:41:19.112 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.112 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.112 else:
2025-07-02 06:41:19.112 # the synch pair is identical
2025-07-02 06:41:19.112 yield ' ' + aelt
2025-07-02 06:41:19.112
2025-07-02 06:41:19.112 # pump out diffs from after the synch point
2025-07-02 06:41:19.112 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.112
2025-07-02 06:41:19.112 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.112 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.113 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.113 alo = 515, ahi = 1101
2025-07-02 06:41:19.113 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.113 blo = 515, bhi = 1101
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.113 g = []
2025-07-02 06:41:19.113 if alo < ahi:
2025-07-02 06:41:19.113 if blo < bhi:
2025-07-02 06:41:19.113 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.113 else:
2025-07-02 06:41:19.113 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.113 elif blo < bhi:
2025-07-02 06:41:19.113 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 > yield from g
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.114 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.114 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.114 alo = 515, ahi = 1101
2025-07-02 06:41:19.114 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.114 blo = 515, bhi = 1101
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.114 r"""
2025-07-02 06:41:19.114 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.114 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.114 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.114 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114 Example:
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114 >>> d = Differ()
2025-07-02 06:41:19.115 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.115 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.115 >>> print(''.join(results), end="")
2025-07-02 06:41:19.115 - abcDefghiJkl
2025-07-02 06:41:19.115 + abcdefGhijkl
2025-07-02 06:41:19.115 """
2025-07-02 06:41:19.115
2025-07-02 06:41:19.115 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.115 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.115 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.115 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.115 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.115
2025-07-02 06:41:19.115 # search for the pair that matches best without being identical
2025-07-02 06:41:19.115 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.115 # on junk -- unless we have to)
2025-07-02 06:41:19.116 for j in range(blo, bhi):
2025-07-02 06:41:19.116 bj = b[j]
2025-07-02 06:41:19.116 cruncher.set_seq2(bj)
2025-07-02 06:41:19.116 for i in range(alo, ahi):
2025-07-02 06:41:19.116 ai = a[i]
2025-07-02 06:41:19.116 if ai == bj:
2025-07-02 06:41:19.116 if eqi is None:
2025-07-02 06:41:19.116 eqi, eqj = i, j
2025-07-02 06:41:19.116 continue
2025-07-02 06:41:19.116 cruncher.set_seq1(ai)
2025-07-02 06:41:19.116 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.116 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.116 # compares by a factor of 3.
2025-07-02 06:41:19.116 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.116 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.116 # of the computation is cached by cruncher
2025-07-02 06:41:19.116 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.116 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.116 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.117 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.117 if best_ratio < cutoff:
2025-07-02 06:41:19.117 # no non-identical "pretty close" pair
2025-07-02 06:41:19.117 if eqi is None:
2025-07-02 06:41:19.117 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.117 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.117 return
2025-07-02 06:41:19.117 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.117 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.117 else:
2025-07-02 06:41:19.117 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.117 eqi = None
2025-07-02 06:41:19.117
2025-07-02 06:41:19.117 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.117 # identical
2025-07-02 06:41:19.117
2025-07-02 06:41:19.117 # pump out diffs from before the synch point
2025-07-02 06:41:19.117 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.117
2025-07-02 06:41:19.117 # do intraline marking on the synch pair
2025-07-02 06:41:19.118 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.118 if eqi is None:
2025-07-02 06:41:19.118 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.118 atags = btags = ""
2025-07-02 06:41:19.118 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.118 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.118 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.118 if tag == 'replace':
2025-07-02 06:41:19.118 atags += '^' * la
2025-07-02 06:41:19.118 btags += '^' * lb
2025-07-02 06:41:19.118 elif tag == 'delete':
2025-07-02 06:41:19.118 atags += '-' * la
2025-07-02 06:41:19.118 elif tag == 'insert':
2025-07-02 06:41:19.118 btags += '+' * lb
2025-07-02 06:41:19.118 elif tag == 'equal':
2025-07-02 06:41:19.118 atags += ' ' * la
2025-07-02 06:41:19.118 btags += ' ' * lb
2025-07-02 06:41:19.118 else:
2025-07-02 06:41:19.118 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.118 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.119 else:
2025-07-02 06:41:19.119 # the synch pair is identical
2025-07-02 06:41:19.119 yield ' ' + aelt
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119 # pump out diffs from after the synch point
2025-07-02 06:41:19.119 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.119 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.119 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.119 alo = 516, ahi = 1101
2025-07-02 06:41:19.119 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.119 blo = 516, bhi = 1101
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.119 g = []
2025-07-02 06:41:19.119 if alo < ahi:
2025-07-02 06:41:19.119 if blo < bhi:
2025-07-02 06:41:19.120 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.120 else:
2025-07-02 06:41:19.120 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.120 elif blo < bhi:
2025-07-02 06:41:19.120 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 > yield from g
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.120 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.120 alo = 516, ahi = 1101
2025-07-02 06:41:19.120 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.120 blo = 516, bhi = 1101
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.120 r"""
2025-07-02 06:41:19.120 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.121 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.121 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.121 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.121
2025-07-02 06:41:19.121 Example:
2025-07-02 06:41:19.121
2025-07-02 06:41:19.121 >>> d = Differ()
2025-07-02 06:41:19.121 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.121 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.121 >>> print(''.join(results), end="")
2025-07-02 06:41:19.121 - abcDefghiJkl
2025-07-02 06:41:19.121 + abcdefGhijkl
2025-07-02 06:41:19.121 """
2025-07-02 06:41:19.121
2025-07-02 06:41:19.121 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.121 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.121 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.121 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.122 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.122
2025-07-02 06:41:19.122 # search for the pair that matches best without being identical
2025-07-02 06:41:19.122 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.122 # on junk -- unless we have to)
2025-07-02 06:41:19.122 for j in range(blo, bhi):
2025-07-02 06:41:19.122 bj = b[j]
2025-07-02 06:41:19.122 cruncher.set_seq2(bj)
2025-07-02 06:41:19.122 for i in range(alo, ahi):
2025-07-02 06:41:19.122 ai = a[i]
2025-07-02 06:41:19.122 if ai == bj:
2025-07-02 06:41:19.122 if eqi is None:
2025-07-02 06:41:19.122 eqi, eqj = i, j
2025-07-02 06:41:19.122 continue
2025-07-02 06:41:19.122 cruncher.set_seq1(ai)
2025-07-02 06:41:19.122 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.122 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.122 # compares by a factor of 3.
2025-07-02 06:41:19.122 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.123 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.123 # of the computation is cached by cruncher
2025-07-02 06:41:19.123 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.123 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.123 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.123 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.123 if best_ratio < cutoff:
2025-07-02 06:41:19.123 # no non-identical "pretty close" pair
2025-07-02 06:41:19.123 if eqi is None:
2025-07-02 06:41:19.123 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.123 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.123 return
2025-07-02 06:41:19.123 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.123 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.123 else:
2025-07-02 06:41:19.123 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.123 eqi = None
2025-07-02 06:41:19.123
2025-07-02 06:41:19.124 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.124 # identical
2025-07-02 06:41:19.124
2025-07-02 06:41:19.124 # pump out diffs from before the synch point
2025-07-02 06:41:19.124 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.124
2025-07-02 06:41:19.124 # do intraline marking on the synch pair
2025-07-02 06:41:19.124 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.124 if eqi is None:
2025-07-02 06:41:19.124 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.124 atags = btags = ""
2025-07-02 06:41:19.124 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.124 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.124 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.124 if tag == 'replace':
2025-07-02 06:41:19.124 atags += '^' * la
2025-07-02 06:41:19.124 btags += '^' * lb
2025-07-02 06:41:19.124 elif tag == 'delete':
2025-07-02 06:41:19.124 atags += '-' * la
2025-07-02 06:41:19.124 elif tag == 'insert':
2025-07-02 06:41:19.125 btags += '+' * lb
2025-07-02 06:41:19.125 elif tag == 'equal':
2025-07-02 06:41:19.125 atags += ' ' * la
2025-07-02 06:41:19.125 btags += ' ' * lb
2025-07-02 06:41:19.125 else:
2025-07-02 06:41:19.125 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.125 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.125 else:
2025-07-02 06:41:19.125 # the synch pair is identical
2025-07-02 06:41:19.125 yield ' ' + aelt
2025-07-02 06:41:19.125
2025-07-02 06:41:19.125 # pump out diffs from after the synch point
2025-07-02 06:41:19.125 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.125
2025-07-02 06:41:19.125 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.125 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.125
2025-07-02 06:41:19.125 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.125 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.126 alo = 517, ahi = 1101
2025-07-02 06:41:19.126 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.126 blo = 517, bhi = 1101
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.126 g = []
2025-07-02 06:41:19.126 if alo < ahi:
2025-07-02 06:41:19.126 if blo < bhi:
2025-07-02 06:41:19.126 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.126 else:
2025-07-02 06:41:19.126 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.126 elif blo < bhi:
2025-07-02 06:41:19.126 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 > yield from g
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.126 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.127 alo = 517, ahi = 1101
2025-07-02 06:41:19.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.127 blo = 517, bhi = 1101
2025-07-02 06:41:19.127
2025-07-02 06:41:19.127 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.127 r"""
2025-07-02 06:41:19.127 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.127 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.127 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.127 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.127
2025-07-02 06:41:19.127 Example:
2025-07-02 06:41:19.127
2025-07-02 06:41:19.127 >>> d = Differ()
2025-07-02 06:41:19.127 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.127 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.127 >>> print(''.join(results), end="")
2025-07-02 06:41:19.127 - abcDefghiJkl
2025-07-02 06:41:19.128 + abcdefGhijkl
2025-07-02 06:41:19.128 """
2025-07-02 06:41:19.128
2025-07-02 06:41:19.128 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.128 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.128 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.128 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.128 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.128
2025-07-02 06:41:19.128 # search for the pair that matches best without being identical
2025-07-02 06:41:19.128 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.128 # on junk -- unless we have to)
2025-07-02 06:41:19.128 for j in range(blo, bhi):
2025-07-02 06:41:19.128 bj = b[j]
2025-07-02 06:41:19.128 cruncher.set_seq2(bj)
2025-07-02 06:41:19.128 for i in range(alo, ahi):
2025-07-02 06:41:19.128 ai = a[i]
2025-07-02 06:41:19.128 if ai == bj:
2025-07-02 06:41:19.128 if eqi is None:
2025-07-02 06:41:19.128 eqi, eqj = i, j
2025-07-02 06:41:19.129 continue
2025-07-02 06:41:19.129 cruncher.set_seq1(ai)
2025-07-02 06:41:19.129 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.129 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.129 # compares by a factor of 3.
2025-07-02 06:41:19.129 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.129 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.129 # of the computation is cached by cruncher
2025-07-02 06:41:19.129 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.129 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.129 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.129 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.129 if best_ratio < cutoff:
2025-07-02 06:41:19.129 # no non-identical "pretty close" pair
2025-07-02 06:41:19.129 if eqi is None:
2025-07-02 06:41:19.129 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.129 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.129 return
2025-07-02 06:41:19.129 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.129 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.130 else:
2025-07-02 06:41:19.130 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.130 eqi = None
2025-07-02 06:41:19.130
2025-07-02 06:41:19.130 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.130 # identical
2025-07-02 06:41:19.130
2025-07-02 06:41:19.130 # pump out diffs from before the synch point
2025-07-02 06:41:19.130 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.130
2025-07-02 06:41:19.130 # do intraline marking on the synch pair
2025-07-02 06:41:19.130 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.130 if eqi is None:
2025-07-02 06:41:19.130 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.130 atags = btags = ""
2025-07-02 06:41:19.130 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.130 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.130 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.130 if tag == 'replace':
2025-07-02 06:41:19.130 atags += '^' * la
2025-07-02 06:41:19.131 btags += '^' * lb
2025-07-02 06:41:19.131 elif tag == 'delete':
2025-07-02 06:41:19.131 atags += '-' * la
2025-07-02 06:41:19.131 elif tag == 'insert':
2025-07-02 06:41:19.131 btags += '+' * lb
2025-07-02 06:41:19.131 elif tag == 'equal':
2025-07-02 06:41:19.131 atags += ' ' * la
2025-07-02 06:41:19.131 btags += ' ' * lb
2025-07-02 06:41:19.131 else:
2025-07-02 06:41:19.131 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.131 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.131 else:
2025-07-02 06:41:19.131 # the synch pair is identical
2025-07-02 06:41:19.131 yield ' ' + aelt
2025-07-02 06:41:19.131
2025-07-02 06:41:19.131 # pump out diffs from after the synch point
2025-07-02 06:41:19.131 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.131
2025-07-02 06:41:19.132 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.132 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.132
2025-07-02 06:41:19.132 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.132 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.132 alo = 518, ahi = 1101
2025-07-02 06:41:19.132 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.132 blo = 518, bhi = 1101
2025-07-02 06:41:19.132
2025-07-02 06:41:19.132 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.132 g = []
2025-07-02 06:41:19.132 if alo < ahi:
2025-07-02 06:41:19.132 if blo < bhi:
2025-07-02 06:41:19.132 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.132 else:
2025-07-02 06:41:19.132 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.132 elif blo < bhi:
2025-07-02 06:41:19.132 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 > yield from g
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.133 alo = 518, ahi = 1101
2025-07-02 06:41:19.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.133 blo = 518, bhi = 1101
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.133 r"""
2025-07-02 06:41:19.133 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.133 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.133 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.133 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.133
2025-07-02 06:41:19.134 Example:
2025-07-02 06:41:19.134
2025-07-02 06:41:19.134 >>> d = Differ()
2025-07-02 06:41:19.134 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.134 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.134 >>> print(''.join(results), end="")
2025-07-02 06:41:19.134 - abcDefghiJkl
2025-07-02 06:41:19.134 + abcdefGhijkl
2025-07-02 06:41:19.134 """
2025-07-02 06:41:19.134
2025-07-02 06:41:19.134 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.134 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.134 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.134 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.134 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.134
2025-07-02 06:41:19.134 # search for the pair that matches best without being identical
2025-07-02 06:41:19.134 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.135 # on junk -- unless we have to)
2025-07-02 06:41:19.135 for j in range(blo, bhi):
2025-07-02 06:41:19.135 bj = b[j]
2025-07-02 06:41:19.135 cruncher.set_seq2(bj)
2025-07-02 06:41:19.135 for i in range(alo, ahi):
2025-07-02 06:41:19.135 ai = a[i]
2025-07-02 06:41:19.135 if ai == bj:
2025-07-02 06:41:19.135 if eqi is None:
2025-07-02 06:41:19.135 eqi, eqj = i, j
2025-07-02 06:41:19.135 continue
2025-07-02 06:41:19.135 cruncher.set_seq1(ai)
2025-07-02 06:41:19.135 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.135 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.135 # compares by a factor of 3.
2025-07-02 06:41:19.135 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.135 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.135 # of the computation is cached by cruncher
2025-07-02 06:41:19.135 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.135 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.136 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.136 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.136 if best_ratio < cutoff:
2025-07-02 06:41:19.136 # no non-identical "pretty close" pair
2025-07-02 06:41:19.136 if eqi is None:
2025-07-02 06:41:19.136 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.136 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.136 return
2025-07-02 06:41:19.136 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.136 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.136 else:
2025-07-02 06:41:19.136 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.136 eqi = None
2025-07-02 06:41:19.136
2025-07-02 06:41:19.136 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.136 # identical
2025-07-02 06:41:19.136
2025-07-02 06:41:19.136 # pump out diffs from before the synch point
2025-07-02 06:41:19.136 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.137
2025-07-02 06:41:19.137 # do intraline marking on the synch pair
2025-07-02 06:41:19.137 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.137 if eqi is None:
2025-07-02 06:41:19.137 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.137 atags = btags = ""
2025-07-02 06:41:19.137 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.137 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.137 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.137 if tag == 'replace':
2025-07-02 06:41:19.137 atags += '^' * la
2025-07-02 06:41:19.137 btags += '^' * lb
2025-07-02 06:41:19.137 elif tag == 'delete':
2025-07-02 06:41:19.137 atags += '-' * la
2025-07-02 06:41:19.137 elif tag == 'insert':
2025-07-02 06:41:19.137 btags += '+' * lb
2025-07-02 06:41:19.137 elif tag == 'equal':
2025-07-02 06:41:19.137 atags += ' ' * la
2025-07-02 06:41:19.137 btags += ' ' * lb
2025-07-02 06:41:19.137 else:
2025-07-02 06:41:19.138 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.138 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.138 else:
2025-07-02 06:41:19.138 # the synch pair is identical
2025-07-02 06:41:19.138 yield ' ' + aelt
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138 # pump out diffs from after the synch point
2025-07-02 06:41:19.138 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.138 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.138 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.138 alo = 519, ahi = 1101
2025-07-02 06:41:19.138 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.138 blo = 519, bhi = 1101
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.138 g = []
2025-07-02 06:41:19.139 if alo < ahi:
2025-07-02 06:41:19.139 if blo < bhi:
2025-07-02 06:41:19.139 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.139 else:
2025-07-02 06:41:19.139 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.139 elif blo < bhi:
2025-07-02 06:41:19.139 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 > yield from g
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.139 alo = 519, ahi = 1101
2025-07-02 06:41:19.139 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.139 blo = 519, bhi = 1101
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.140 r"""
2025-07-02 06:41:19.140 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.140 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.140 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.140 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.140
2025-07-02 06:41:19.140 Example:
2025-07-02 06:41:19.140
2025-07-02 06:41:19.140 >>> d = Differ()
2025-07-02 06:41:19.140 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.140 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.140 >>> print(''.join(results), end="")
2025-07-02 06:41:19.140 - abcDefghiJkl
2025-07-02 06:41:19.140 + abcdefGhijkl
2025-07-02 06:41:19.140 """
2025-07-02 06:41:19.140
2025-07-02 06:41:19.140 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.140 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.141 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.141 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.141 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.141
2025-07-02 06:41:19.141 # search for the pair that matches best without being identical
2025-07-02 06:41:19.141 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.141 # on junk -- unless we have to)
2025-07-02 06:41:19.141 for j in range(blo, bhi):
2025-07-02 06:41:19.141 bj = b[j]
2025-07-02 06:41:19.141 cruncher.set_seq2(bj)
2025-07-02 06:41:19.141 for i in range(alo, ahi):
2025-07-02 06:41:19.141 ai = a[i]
2025-07-02 06:41:19.141 if ai == bj:
2025-07-02 06:41:19.141 if eqi is None:
2025-07-02 06:41:19.141 eqi, eqj = i, j
2025-07-02 06:41:19.141 continue
2025-07-02 06:41:19.141 cruncher.set_seq1(ai)
2025-07-02 06:41:19.141 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.141 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.142 # compares by a factor of 3.
2025-07-02 06:41:19.142 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.142 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.142 # of the computation is cached by cruncher
2025-07-02 06:41:19.142 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.142 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.142 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.142 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.142 if best_ratio < cutoff:
2025-07-02 06:41:19.142 # no non-identical "pretty close" pair
2025-07-02 06:41:19.142 if eqi is None:
2025-07-02 06:41:19.142 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.142 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.142 return
2025-07-02 06:41:19.142 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.142 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.142 else:
2025-07-02 06:41:19.142 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.142 eqi = None
2025-07-02 06:41:19.143
2025-07-02 06:41:19.143 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.143 # identical
2025-07-02 06:41:19.143
2025-07-02 06:41:19.143 # pump out diffs from before the synch point
2025-07-02 06:41:19.143 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.143
2025-07-02 06:41:19.143 # do intraline marking on the synch pair
2025-07-02 06:41:19.143 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.143 if eqi is None:
2025-07-02 06:41:19.143 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.143 atags = btags = ""
2025-07-02 06:41:19.143 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.143 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.143 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.143 if tag == 'replace':
2025-07-02 06:41:19.143 atags += '^' * la
2025-07-02 06:41:19.143 btags += '^' * lb
2025-07-02 06:41:19.143 elif tag == 'delete':
2025-07-02 06:41:19.144 atags += '-' * la
2025-07-02 06:41:19.144 elif tag == 'insert':
2025-07-02 06:41:19.144 btags += '+' * lb
2025-07-02 06:41:19.144 elif tag == 'equal':
2025-07-02 06:41:19.144 atags += ' ' * la
2025-07-02 06:41:19.144 btags += ' ' * lb
2025-07-02 06:41:19.144 else:
2025-07-02 06:41:19.144 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.144 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.144 else:
2025-07-02 06:41:19.144 # the synch pair is identical
2025-07-02 06:41:19.144 yield ' ' + aelt
2025-07-02 06:41:19.144
2025-07-02 06:41:19.144 # pump out diffs from after the synch point
2025-07-02 06:41:19.144 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.144
2025-07-02 06:41:19.144 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.144 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.144
2025-07-02 06:41:19.144 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.145 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.145 alo = 520, ahi = 1101
2025-07-02 06:41:19.145 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.145 blo = 520, bhi = 1101
2025-07-02 06:41:19.145
2025-07-02 06:41:19.145 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.145 g = []
2025-07-02 06:41:19.145 if alo < ahi:
2025-07-02 06:41:19.145 if blo < bhi:
2025-07-02 06:41:19.145 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.145 else:
2025-07-02 06:41:19.145 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.145 elif blo < bhi:
2025-07-02 06:41:19.145 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.145
2025-07-02 06:41:19.145 > yield from g
2025-07-02 06:41:19.145
2025-07-02 06:41:19.145 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.146 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.146 alo = 520, ahi = 1101
2025-07-02 06:41:19.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.146 blo = 520, bhi = 1101
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.146 r"""
2025-07-02 06:41:19.146 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.146 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.146 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.146 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146 Example:
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146 >>> d = Differ()
2025-07-02 06:41:19.147 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.147 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.147 >>> print(''.join(results), end="")
2025-07-02 06:41:19.147 - abcDefghiJkl
2025-07-02 06:41:19.147 + abcdefGhijkl
2025-07-02 06:41:19.147 """
2025-07-02 06:41:19.147
2025-07-02 06:41:19.147 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.147 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.147 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.147 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.147 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.147
2025-07-02 06:41:19.147 # search for the pair that matches best without being identical
2025-07-02 06:41:19.147 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.147 # on junk -- unless we have to)
2025-07-02 06:41:19.147 for j in range(blo, bhi):
2025-07-02 06:41:19.147 bj = b[j]
2025-07-02 06:41:19.148 cruncher.set_seq2(bj)
2025-07-02 06:41:19.148 for i in range(alo, ahi):
2025-07-02 06:41:19.148 ai = a[i]
2025-07-02 06:41:19.148 if ai == bj:
2025-07-02 06:41:19.148 if eqi is None:
2025-07-02 06:41:19.148 eqi, eqj = i, j
2025-07-02 06:41:19.148 continue
2025-07-02 06:41:19.148 cruncher.set_seq1(ai)
2025-07-02 06:41:19.148 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.148 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.148 # compares by a factor of 3.
2025-07-02 06:41:19.148 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.148 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.148 # of the computation is cached by cruncher
2025-07-02 06:41:19.148 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.148 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.148 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.148 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.148 if best_ratio < cutoff:
2025-07-02 06:41:19.148 # no non-identical "pretty close" pair
2025-07-02 06:41:19.149 if eqi is None:
2025-07-02 06:41:19.149 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.149 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.149 return
2025-07-02 06:41:19.149 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.149 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.149 else:
2025-07-02 06:41:19.149 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.149 eqi = None
2025-07-02 06:41:19.149
2025-07-02 06:41:19.149 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.149 # identical
2025-07-02 06:41:19.149
2025-07-02 06:41:19.149 # pump out diffs from before the synch point
2025-07-02 06:41:19.149 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.149
2025-07-02 06:41:19.149 # do intraline marking on the synch pair
2025-07-02 06:41:19.149 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.149 if eqi is None:
2025-07-02 06:41:19.149 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.149 atags = btags = ""
2025-07-02 06:41:19.150 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.150 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.150 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.150 if tag == 'replace':
2025-07-02 06:41:19.150 atags += '^' * la
2025-07-02 06:41:19.150 btags += '^' * lb
2025-07-02 06:41:19.150 elif tag == 'delete':
2025-07-02 06:41:19.150 atags += '-' * la
2025-07-02 06:41:19.150 elif tag == 'insert':
2025-07-02 06:41:19.150 btags += '+' * lb
2025-07-02 06:41:19.150 elif tag == 'equal':
2025-07-02 06:41:19.150 atags += ' ' * la
2025-07-02 06:41:19.150 btags += ' ' * lb
2025-07-02 06:41:19.150 else:
2025-07-02 06:41:19.150 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.150 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.150 else:
2025-07-02 06:41:19.151 # the synch pair is identical
2025-07-02 06:41:19.151 yield ' ' + aelt
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151 # pump out diffs from after the synch point
2025-07-02 06:41:19.151 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.151 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.151 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.151 alo = 521, ahi = 1101
2025-07-02 06:41:19.151 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.151 blo = 521, bhi = 1101
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.151 g = []
2025-07-02 06:41:19.151 if alo < ahi:
2025-07-02 06:41:19.151 if blo < bhi:
2025-07-02 06:41:19.152 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.152 else:
2025-07-02 06:41:19.152 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.152 elif blo < bhi:
2025-07-02 06:41:19.152 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 > yield from g
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.152 alo = 521, ahi = 1101
2025-07-02 06:41:19.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.152 blo = 521, bhi = 1101
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.152 r"""
2025-07-02 06:41:19.153 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.153 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.153 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.153 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.153
2025-07-02 06:41:19.153 Example:
2025-07-02 06:41:19.153
2025-07-02 06:41:19.153 >>> d = Differ()
2025-07-02 06:41:19.153 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.153 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.153 >>> print(''.join(results), end="")
2025-07-02 06:41:19.153 - abcDefghiJkl
2025-07-02 06:41:19.153 + abcdefGhijkl
2025-07-02 06:41:19.153 """
2025-07-02 06:41:19.153
2025-07-02 06:41:19.153 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.153 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.154 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.154 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.154 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 06:41:19.154
2025-07-02 06:41:19.154 # search for the pair that matches best without being identical
2025-07-02 06:41:19.154 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.154 # on junk -- unless we have to)
2025-07-02 06:41:19.154 for j in range(blo, bhi):
2025-07-02 06:41:19.154 bj = b[j]
2025-07-02 06:41:19.154 cruncher.set_seq2(bj)
2025-07-02 06:41:19.154 for i in range(alo, ahi):
2025-07-02 06:41:19.154 ai = a[i]
2025-07-02 06:41:19.154 if ai == bj:
2025-07-02 06:41:19.154 if eqi is None:
2025-07-02 06:41:19.154 eqi, eqj = i, j
2025-07-02 06:41:19.154 continue
2025-07-02 06:41:19.154 cruncher.set_seq1(ai)
2025-07-02 06:41:19.154 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.154 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.155 # compares by a factor of 3.
2025-07-02 06:41:19.155 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.155 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.155 # of the computation is cached by cruncher
2025-07-02 06:41:19.155 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.155 cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.155 cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.155 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.155 if best_ratio < cutoff:
2025-07-02 06:41:19.155 # no non-identical "pretty close" pair
2025-07-02 06:41:19.155 if eqi is None:
2025-07-02 06:41:19.155 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.155 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.155 return
2025-07-02 06:41:19.155 # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.155 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.155 else:
2025-07-02 06:41:19.155 # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.155 eqi = None
2025-07-02 06:41:19.156
2025-07-02 06:41:19.156 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.156 # identical
2025-07-02 06:41:19.156
2025-07-02 06:41:19.156 # pump out diffs from before the synch point
2025-07-02 06:41:19.156 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.156
2025-07-02 06:41:19.156 # do intraline marking on the synch pair
2025-07-02 06:41:19.156 aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.156 if eqi is None:
2025-07-02 06:41:19.156 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.156 atags = btags = ""
2025-07-02 06:41:19.156 cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.156 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.156 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.156 if tag == 'replace':
2025-07-02 06:41:19.156 atags += '^' * la
2025-07-02 06:41:19.156 btags += '^' * lb
2025-07-02 06:41:19.156 elif tag == 'delete':
2025-07-02 06:41:19.156 atags += '-' * la
2025-07-02 06:41:19.157 elif tag == 'insert':
2025-07-02 06:41:19.157 btags += '+' * lb
2025-07-02 06:41:19.157 elif tag == 'equal':
2025-07-02 06:41:19.157 atags += ' ' * la
2025-07-02 06:41:19.157 btags += ' ' * lb
2025-07-02 06:41:19.157 else:
2025-07-02 06:41:19.157 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.157 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.157 else:
2025-07-02 06:41:19.157 # the synch pair is identical
2025-07-02 06:41:19.157 yield ' ' + aelt
2025-07-02 06:41:19.157
2025-07-02 06:41:19.157 # pump out diffs from after the synch point
2025-07-02 06:41:19.157 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.157
2025-07-02 06:41:19.157 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.157 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.157
2025-07-02 06:41:19.157 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.157 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.158 alo = 522, ahi = 1101
2025-07-02 06:41:19.158 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.158 blo = 522, bhi = 1101
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.158 g = []
2025-07-02 06:41:19.158 if alo < ahi:
2025-07-02 06:41:19.158 if blo < bhi:
2025-07-02 06:41:19.158 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.158 else:
2025-07-02 06:41:19.158 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.158 elif blo < bhi:
2025-07-02 06:41:19.158 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 > yield from g
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.159 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 06:41:19.159 alo = 522, ahi = 1101
2025-07-02 06:41:19.159 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 06:41:19.159 blo = 522, bhi = 1101
2025-07-02 06:41:19.159
2025-07-02 06:41:19.159 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.159 r"""
2025-07-02 06:41:19.159 When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.159 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.159 synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.159 similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.159
2025-07-02 06:41:19.159 Example:
2025-07-02 06:41:19.159
2025-07-02 06:41:19.159 >>> d = Differ()
2025-07-02 06:41:19.159 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.159 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.159 >>> print(''.join(results), end="")
2025-07-02 06:41:19.159 - abcDefghiJkl
2025-07-02 06:41:19.160 + abcdefGhijkl
2025-07-02 06:41:19.160 """
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160 # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.160 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.160 best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.160 > cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160 C:\Python3x\Lib\difflib.py:915:
2025-07-02 06:41:19.160 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160 self = <difflib.SequenceMatcher object at [hex]>
2025-07-02 06:41:19.160 isjunk = <function IS_CHARACTER_JUNK at 0x000002A86576DC60>, a = '', b = ''
2025-07-02 06:41:19.160 autojunk = True
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160 def __init__(self, isjunk=None, a='', b='', autojunk=True):
2025-07-02 06:41:19.160 """Construct a SequenceMatcher.
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161 Optional arg isjunk is None (the default), or a one-argument
2025-07-02 06:41:19.161 function that takes a sequence element and returns true iff the
2025-07-02 06:41:19.161 element is junk. None is equivalent to passing "lambda x: 0", i.e.
2025-07-02 06:41:19.161 no elements are considered to be junk. For example, pass
2025-07-02 06:41:19.161 lambda x: x in " \\t"
2025-07-02 06:41:19.161 if you're comparing lines as sequences of characters, and don't
2025-07-02 06:41:19.161 want to synch up on blanks or hard tabs.
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161 Optional arg a is the first of two sequences to be compared. By
2025-07-02 06:41:19.161 default, an empty string. The elements of a must be hashable. See
2025-07-02 06:41:19.161 also .set_seqs() and .set_seq1().
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161 Optional arg b is the second of two sequences to be compared. By
2025-07-02 06:41:19.161 default, an empty string. The elements of b must be hashable. See
2025-07-02 06:41:19.161 also .set_seqs() and .set_seq2().
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161 Optional arg autojunk should be set to False to disable the
2025-07-02 06:41:19.162 "automatic junk heuristic" that treats popular elements as junk
2025-07-02 06:41:19.162 (see module documentation for more information).
2025-07-02 06:41:19.162 """
2025-07-02 06:41:19.162
2025-07-02 06:41:19.162 # Members:
2025-07-02 06:41:19.162 # a
2025-07-02 06:41:19.162 # first sequence
2025-07-02 06:41:19.162 # b
2025-07-02 06:41:19.162 # second sequence; differences are computed as "what do
2025-07-02 06:41:19.162 # we need to do to 'a' to change it into 'b'?"
2025-07-02 06:41:19.162 # b2j
2025-07-02 06:41:19.162 # for x in b, b2j[x] is a list of the indices (into b)
2025-07-02 06:41:19.162 # at which x appears; junk and popular elements do not appear
2025-07-02 06:41:19.162 # fullbcount
2025-07-02 06:41:19.162 # for x in b, fullbcount[x] == the number of times x
2025-07-02 06:41:19.162 # appears in b; only materialized if really needed (used
2025-07-02 06:41:19.162 # only for computing quick_ratio())
2025-07-02 06:41:19.162 # matching_blocks
2025-07-02 06:41:19.162 # a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
2025-07-02 06:41:19.163 # ascending & non-overlapping in i and in j; terminated by
2025-07-02 06:41:19.163 # a dummy (len(a), len(b), 0) sentinel
2025-07-02 06:41:19.163 # opcodes
2025-07-02 06:41:19.163 # a list of (tag, i1, i2, j1, j2) tuples, where tag is
2025-07-02 06:41:19.163 # one of
2025-07-02 06:41:19.163 # 'replace' a[i1:i2] should be replaced by b[j1:j2]
2025-07-02 06:41:19.163 # 'delete' a[i1:i2] should be deleted
2025-07-02 06:41:19.163 # 'insert' b[j1:j2] should be inserted
2025-07-02 06:41:19.163 # 'equal' a[i1:i2] == b[j1:j2]
2025-07-02 06:41:19.163 # isjunk
2025-07-02 06:41:19.163 # a user-supplied function taking a sequence element and
2025-07-02 06:41:19.163 # returning true iff the element is "junk" -- this has
2025-07-02 06:41:19.163 # subtle but helpful effects on the algorithm, which I'll
2025-07-02 06:41:19.163 # get around to writing up someday <0.9 wink>.
2025-07-02 06:41:19.163 # DON'T USE! Only __chain_b uses this. Use "in self.bjunk".
2025-07-02 06:41:19.163 # bjunk
2025-07-02 06:41:19.163 # the items in b for which isjunk is True.
2025-07-02 06:41:19.163 # bpopular
2025-07-02 06:41:19.163 # nonjunk items in b treated as junk by the heuristic (if used).
2025-07-02 06:41:19.163
2025-07-02 06:41:19.164 self.isjunk = isjunk
2025-07-02 06:41:19.164 self.a = self.b = None
2025-07-02 06:41:19.164 self.autojunk = autojunk
2025-07-02 06:41:19.164 > self.set_seqs(a, b)
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 C:\Python3x\Lib\difflib.py:182:
2025-07-02 06:41:19.164 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 self = <difflib.SequenceMatcher object at [hex]>, a = '', b = ''
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 def set_seqs(self, a, b):
2025-07-02 06:41:19.164 """Set the two sequences to be compared.
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 >>> s = SequenceMatcher()
2025-07-02 06:41:19.164 >>> s.set_seqs("abcd", "bcde")
2025-07-02 06:41:19.164 >>> s.ratio()
2025-07-02 06:41:19.164 0.75
2025-07-02 06:41:19.164 """
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 self.set_seq1(a)
2025-07-02 06:41:19.164 > self.set_seq2(b)
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 C:\Python3x\Lib\difflib.py:194:
2025-07-02 06:41:19.165 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 self = <difflib.SequenceMatcher object at [hex]>, b = ''
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 def set_seq2(self, b):
2025-07-02 06:41:19.165 """Set the second sequence to be compared.
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 The first sequence to be compared is not changed.
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 >>> s = SequenceMatcher(None, "abcd", "bcde")
2025-07-02 06:41:19.165 >>> s.ratio()
2025-07-02 06:41:19.165 0.75
2025-07-02 06:41:19.165 >>> s.set_seq2("abcd")
2025-07-02 06:41:19.165 >>> s.ratio()
2025-07-02 06:41:19.165 1.0
2025-07-02 06:41:19.165 >>>
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 SequenceMatcher computes and caches detailed information about the
2025-07-02 06:41:19.166 second sequence, so if you want to compare one sequence S against
2025-07-02 06:41:19.166 many sequences, use .set_seq2(S) once and call .set_seq1(x)
2025-07-02 06:41:19.166 repeatedly for each of the other sequences.
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 See also set_seqs() and set_seq1().
2025-07-02 06:41:19.166 """
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 if b is self.b:
2025-07-02 06:41:19.166 return
2025-07-02 06:41:19.166 self.b = b
2025-07-02 06:41:19.166 self.matching_blocks = self.opcodes = None
2025-07-02 06:41:19.166 self.fullbcount = None
2025-07-02 06:41:19.166 > self.__chain_b()
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 C:\Python3x\Lib\difflib.py:248:
2025-07-02 06:41:19.166 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 self = <difflib.SequenceMatcher object at [hex]>
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 def __chain_b(self):
2025-07-02 06:41:19.167 # Because isjunk is a user-defined (not C) function, and we test
2025-07-02 06:41:19.167 # for junk a LOT, it's important to minimize the number of calls.
2025-07-02 06:41:19.167 # Before the tricks described here, __chain_b was by far the most
2025-07-02 06:41:19.167 # time-consuming routine in the whole module! If anyone sees
2025-07-02 06:41:19.167 # Jim Roskind, thank him again for profile.py -- I never would
2025-07-02 06:41:19.167 # have guessed that.
2025-07-02 06:41:19.167 # The first trick is to build b2j ignoring the possibility
2025-07-02 06:41:19.167 # of junk. I.e., we don't call isjunk at all yet. Throwing
2025-07-02 06:41:19.167 # out the junk later is much cheaper than building b2j "right"
2025-07-02 06:41:19.167 # from the start.
2025-07-02 06:41:19.167 b = self.b
2025-07-02 06:41:19.167 self.b2j = b2j = {}
2025-07-02 06:41:19.167
2025-07-02 06:41:19.167 for i, elt in enumerate(b):
2025-07-02 06:41:19.167 indices = b2j.setdefault(elt, [])
2025-07-02 06:41:19.167 indices.append(i)
2025-07-02 06:41:19.167
2025-07-02 06:41:19.167 # Purge junk elements
2025-07-02 06:41:19.167 self.bjunk = junk = set()
2025-07-02 06:41:19.167 isjunk = self.isjunk
2025-07-02 06:41:19.167 if isjunk:
2025-07-02 06:41:19.168 > for elt in b2j.keys():
2025-07-02 06:41:19.168 E RecursionError: maximum recursion depth exceeded while calling a Python object
2025-07-02 06:41:19.168
2025-07-02 06:41:19.168 C:\Python3x\Lib\difflib.py:288: RecursionError
2025-07-02 06:41:19.168 ---------------------------- Captured stdout setup ----------------------------
2025-07-02 06:41:19.168 Creating db: localhost:H:\QA\temp\qa2024.tmp\fbqa\test_1508\test.fdb [page_size=None, sql_dialect=None, charset='NONE', user=SYSDBA, password=masterkey]
|
3 #text |
act = <firebird.qa.plugin.Action pytest object at [hex]>
@pytest.mark.version('>=3')
def test_1(act: Action):
act.expected_stdout = expected_stdout
act.execute()
> assert act.clean_stdout == act.clean_expected_stdout
tests\bugs\core_2969_test.py:1211:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
ops = ('==',), results = (False,)
expls = ('%(py2)s\n{%(py2)s = %(py0)s.clean_stdout\n} == %(py6)s\n{%(py6)s = %(py4)s.clean_expected_stdout\n}',)
each_obj = ('WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var...yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy')
def _call_reprcompare(
ops: Sequence[str],
results: Sequence[bool],
expls: Sequence[str],
each_obj: Sequence[object],
) -> str:
for i, res, expl in zip(range(len(ops)), results, expls):
try:
done = not res
except Exception:
done = True
if done:
break
if util._reprcompare is not None:
> custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
C:\Python3x\Lib\site-packages\_pytest\assertion\rewrite.py:499:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
op = '=='
left = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var_... yyy\n1var_997 yyy\n1var_998 yyy\n1var_999 yyy'
right = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'
def callbinrepr(op, left: object, right: object) -> Optional[str]:
"""Call the pytest_assertrepr_compare hook and prepare the result.
This uses the first result from the hook and then ensures the
following:
* Overly verbose explanations are truncated unless configured otherwise
(eg. if running in verbose mode).
* Embedded newlines are escaped to help util.format_explanation()
later.
* If the rewrite mode is used embedded %-characters are replaced
to protect later % formatting.
The result can be formatted by util.format_explanation() for
pretty printing.
"""
> hook_result = ihook.pytest_assertrepr_compare(
config=item.config, op=op, left=left, right=right
)
C:\Python3x\Lib\site-packages\_pytest\assertion\__init__.py:141:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <HookCaller 'pytest_assertrepr_compare'>
kwargs = {'config': <_pytest.config.Config pytest object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY ...yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'}
firstresult = False
def __call__(self, **kwargs: object) -> Any:
"""Call the hook.
Only accepts keyword arguments, which should match the hook
specification.
Returns the result(s) of calling all registered plugins, see
:ref:`calling`.
"""
assert (
not self.is_historic()
), "Cannot directly call a historic hook - use call_historic instead."
self._verify_all_args_are_provided(kwargs)
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
# Copy because plugins may register other plugins during iteration (#438).
> return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
C:\Python3x\Lib\site-packages\pluggy\_hooks.py:501:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <_pytest.config.PytestPluginManager pytest object at [hex]>
hook_name = 'pytest_assertrepr_compare'
methods = [<HookImpl plugin_name='assertion', plugin=<module '_pytest.assertion' from 'C:\\Python3x\\Lib\\site-packages\\_pytest...plugin_name='firebird', plugin=<module 'firebird.qa.plugin' from 'H:\\QA\\firebird-qa\\src\\firebird\\qa\\plugin.py'>>]
kwargs = {'config': <_pytest.config.Config pytest object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY ...yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'}
firstresult = False
def _hookexec(
self,
hook_name: str,
methods: Sequence[HookImpl],
kwargs: Mapping[str, object],
firstresult: bool,
) -> object | list[object]:
# called from all hookcaller instances.
# enable_tracing will set its own wrapping function at self._inner_hookexec
> return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
C:\Python3x\Lib\site-packages\pluggy\_manager.py:119:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
config = <_pytest.config.Config pytest object at [hex]>, op = '=='
left = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var_... yyy\n1var_997 yyy\n1var_998 yyy\n1var_999 yyy'
right = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997 yyy\n1 var_998 yyy\n1 var_999 yyy'
def pytest_assertrepr_compare(config: Config, op: str, left: object, right: object) -> Optional[List[str]]:
"""Returns explanation for comparisons in failing assert expressions.
If both objects are `str`, uses `difflib.ndiff` to provide explanation.
"""
if isinstance(left, str) and isinstance(right, str) and op == "==":
# 16.11.2023, pzotov: we have to put empty string at the beginning of each comparing lists.
# Otherwise first diff will be at the same line as 'assert' phrase, which causes readability be poor.
#
left_lines = ['']
left_lines.extend(left.splitlines())
right_lines = ['']
right_lines.extend(right.splitlines())
# 16.11.2023, pzotov
# ndiff output must be interpreted as following:
# * "E - <some text>" ==> MISSED line (it was in EXPECTED text but absent in actual one).
# * "E + <some_text>" ==> EXCESSIVE line (it is not in EXPECTED text but did appear in actual).
# But for QA-purposes, this output must answer the question:
# "what must be changed in ACTUAL output so that it became equal to EXPECTED"
# (i.e. how to "REVERT" actual back to expected).
# In order to see such result, we have to specify 'right_lines' to the 1st argument that is passed to ndiff().
# ::: NB :::
# We assume that all tests are written so that ACTUAL output is left side in 'assert' statement and EXPECTED
# is right side, e.g: assert act.clean_stdout == act.clean_expected_stdout
# This requirement is CRUCIAL if we use ndiff() instead of default pytest comparison method!
#
> return list(ndiff(right_lines, left_lines))
src\firebird\qa\plugin.py:608:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
def compare(self, a, b):
r"""
Compare two sequences of lines; generate the resulting delta.
Each sequence must contain individual single-line strings ending with
newlines. Such sequences can be obtained from the `readlines()` method
of file-like objects. The delta generated also consists of newline-
terminated strings, ready to be printed as-is via the writelines()
method of a file-like object.
Example:
>>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
... 'ore\ntree\nemu\n'.splitlines(True))),
... end="")
- one
+ ore
- two
- three
+ tree
+ emu
"""
cruncher = SequenceMatcher(self.linejunk, a, b)
for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
if tag == 'replace':
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
elif tag == 'delete':
g = self._dump('-', a, alo, ahi)
elif tag == 'insert':
g = self._dump('+', b, blo, bhi)
elif tag == 'equal':
g = self._dump(' ', a, alo, ahi)
else:
raise ValueError('unknown tag %r' % (tag,))
> yield from g
C:\Python3x\Lib\difflib.py:872:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 3, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 3, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 4, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 4, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 4, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 4, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 5, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 5, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 5, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 5, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 6, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 6, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 6, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 6, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 7, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 7, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 7, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 7, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 8, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 8, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 8, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 8, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 9, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 9, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 9, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 9, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 10, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 10, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 10, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 10, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 11, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 11, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 11, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 11, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 12, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 12, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 12, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 12, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 13, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 13, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 13, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 13, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 14, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 14, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 14, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 14, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 15, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 15, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 15, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 15, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 16, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 16, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 16, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 16, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 17, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 17, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 17, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 17, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 18, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 18, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 18, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 18, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 19, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 19, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 19, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 19, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 20, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 20, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 20, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 20, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 21, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 21, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 21, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 21, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 22, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 22, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 22, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 22, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 23, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 23, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 23, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 23, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 26, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 26, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 26, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 26, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 27, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 27, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 27, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 27, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 28, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 28, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 28, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 28, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 29, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 29, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 29, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 29, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 30, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 30, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 30, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 30, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 31, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 31, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 31, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 31, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 32, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 32, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 32, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 32, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 33, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 33, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 33, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 33, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 34, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 34, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 34, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 34, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 35, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 35, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 35, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 35, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 36, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 36, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 36, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 36, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 37, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 37, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 37, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 37, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 38, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 38, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 38, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 38, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 39, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 39, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 39, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 39, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 40, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 40, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 40, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 40, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 41, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 41, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 41, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 41, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 42, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 42, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 42, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 42, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 43, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 43, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 43, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 43, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 44, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 44, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 44, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 44, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 45, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 45, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 45, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 45, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 48, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 48, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 48, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 48, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 49, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 49, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 49, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 49, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 50, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 50, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 50, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 50, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 51, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 51, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 51, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 51, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 52, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 52, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 52, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 52, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 53, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 53, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 53, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 53, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 54, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 54, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 54, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 54, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 55, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 55, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 55, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 55, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 56, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 56, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 56, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 56, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 57, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 57, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 57, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 57, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 58, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 58, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 58, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 58, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 59, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 59, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 59, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 59, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 60, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 60, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 60, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 60, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 61, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 61, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 61, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 61, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 62, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 62, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 62, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 62, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 63, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 63, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 63, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 63, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 64, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 64, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 64, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 64, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 65, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 65, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 65, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 65, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 66, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 66, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 66, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 66, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 67, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 67, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 67, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 67, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 70, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 70, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 70, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 70, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 71, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 71, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 71, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 71, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 72, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 72, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 72, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 72, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 73, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 73, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 73, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 73, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 74, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 74, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 74, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 74, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 75, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 75, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 75, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 75, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 76, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 76, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 76, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 76, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 77, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 77, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 77, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 77, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 78, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 78, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 78, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 78, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 79, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 79, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 79, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 79, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 80, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 80, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 80, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 80, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 81, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 81, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 81, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 81, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 82, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 82, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 82, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 82, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 83, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 83, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 83, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 83, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 84, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 84, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 84, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 84, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 85, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 85, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 85, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 85, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 86, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 86, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 86, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 86, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 87, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 87, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 87, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 87, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 88, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 88, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 88, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 88, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 89, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 89, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 89, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 89, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 92, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 92, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 92, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 92, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 93, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 93, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 93, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 93, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 94, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 94, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 94, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 94, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 95, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 95, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 95, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 95, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 96, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 96, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 96, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 96, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 97, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 97, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 97, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 97, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 98, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 98, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 98, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 98, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 99, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 99, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 99, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 99, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 100, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 100, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 100, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 100, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 101, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 101, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 101, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 101, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 102, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 102, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 102, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 102, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 103, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 103, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 103, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 103, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 104, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 104, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 104, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 104, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 105, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 105, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 105, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 105, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 106, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 106, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 106, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 106, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 107, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 107, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 107, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 107, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 108, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 108, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 108, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 108, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 109, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 109, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 109, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 109, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 110, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 110, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 110, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 110, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 111, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 111, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 111, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 111, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 114, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 114, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 114, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 114, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 115, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 115, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 115, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 115, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 116, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 116, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 116, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 116, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 117, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 117, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 117, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 117, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 118, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 118, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 118, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 118, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 119, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 119, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 119, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 119, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 120, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 120, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 120, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 120, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 121, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 121, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 121, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 121, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 122, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 122, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 122, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 122, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 123, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 123, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 123, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 123, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 124, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 124, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 124, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 124, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 125, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 125, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 125, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 125, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 126, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 126, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 126, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 126, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 127, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 127, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 127, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 127, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 128, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 128, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 128, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 128, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 129, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 129, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 129, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 129, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 130, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 130, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 130, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 130, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 131, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 131, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 131, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 131, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 132, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 132, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 132, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 132, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 133, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 133, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 133, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 133, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 136, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 136, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 136, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 136, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 137, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 137, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 137, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 137, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 138, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 138, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 138, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 138, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 139, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 139, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 139, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 139, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 140, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 140, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 140, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 140, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 141, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 141, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 141, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 141, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 142, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 142, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 142, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 142, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 143, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 143, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 143, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 143, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 144, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 144, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 144, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 144, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 145, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 145, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 145, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 145, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 146, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 146, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 146, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 146, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 147, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 147, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 147, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 147, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 148, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 148, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 148, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 148, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 149, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 149, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 149, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 149, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 150, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 150, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 150, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 150, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 151, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 151, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 151, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 151, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 152, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 152, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 152, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 152, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 153, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 153, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 153, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 153, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 154, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 154, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 154, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 154, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 155, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 155, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 155, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 155, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 158, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 158, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 158, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 158, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 159, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 159, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 159, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 159, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 160, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 160, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 160, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 160, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 161, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 161, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 161, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 161, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 162, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 162, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 162, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 162, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 163, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 163, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 163, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 163, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 164, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 164, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 164, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 164, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 165, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 165, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 165, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 165, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 166, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 166, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 166, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 166, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 167, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 167, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 167, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 167, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 168, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 168, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 168, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 168, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 169, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 169, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 169, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 169, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 170, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 170, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 170, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 170, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 171, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 171, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 171, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 171, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 172, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 172, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 172, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 172, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 173, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 173, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 173, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 173, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 174, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 174, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 174, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 174, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 175, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 175, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 175, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 175, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 176, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 176, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 176, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 176, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 177, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 177, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 177, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 177, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 180, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 180, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 180, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 180, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 181, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 181, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 181, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 181, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 182, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 182, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 182, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 182, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 183, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 183, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 183, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 183, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 184, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 184, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 184, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 184, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 185, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 185, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 185, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 185, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 186, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 186, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 186, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 186, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 187, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 187, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 187, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 187, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 188, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 188, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 188, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 188, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 189, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 189, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 189, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 189, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 190, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 190, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 190, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 190, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 191, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 191, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 191, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 191, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 192, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 192, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 192, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 192, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 193, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 193, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 193, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 193, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 194, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 194, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 194, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 194, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 195, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 195, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 195, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 195, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 196, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 196, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 196, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 196, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 197, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 197, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 197, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 197, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 198, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 198, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 198, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 198, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 199, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 199, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 199, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 199, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 202, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 202, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 202, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 202, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 203, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 203, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 203, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 203, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 204, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 204, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 204, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 204, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 205, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 205, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 205, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 205, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 206, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 206, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 206, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 206, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 207, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 207, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 207, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 207, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 208, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 208, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 208, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 208, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 209, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 209, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 209, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 209, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 210, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 210, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 210, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 210, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 211, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 211, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 211, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 211, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 212, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 212, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 212, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 212, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 213, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 213, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 213, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 213, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 214, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 214, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 214, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 214, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 215, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 215, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 215, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 215, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 216, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 216, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 216, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 216, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 217, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 217, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 217, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 217, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 218, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 218, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 218, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 218, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 219, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 219, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 219, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 219, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 220, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 220, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 220, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 220, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 221, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 221, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 221, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 221, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 224, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 224, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 224, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 224, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 225, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 225, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 225, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 225, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 226, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 226, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 226, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 226, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 227, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 227, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 227, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 227, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 228, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 228, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 228, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 228, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 229, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 229, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 229, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 229, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 230, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 230, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 230, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 230, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 231, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 231, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 231, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 231, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 232, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 232, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 232, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 232, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 233, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 233, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 233, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 233, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 234, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 234, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 234, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 234, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 235, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 235, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 235, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 235, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 236, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 236, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 236, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 236, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 237, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 237, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 237, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 237, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 238, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 238, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 238, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 238, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 239, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 239, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 239, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 239, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 240, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 240, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 240, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 240, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 241, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 241, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 241, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 241, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 242, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 242, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 242, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 242, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 243, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 243, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 243, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 243, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 246, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 246, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 246, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 246, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 247, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 247, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 247, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 247, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 248, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 248, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 248, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 248, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 249, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 249, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 249, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 249, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 250, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 250, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 250, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 250, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 251, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 251, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 251, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 251, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 252, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 252, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 252, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 252, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 253, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 253, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 253, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 253, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 254, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 254, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 254, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 254, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 255, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 255, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 255, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 255, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 256, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 256, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 256, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 256, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 257, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 257, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 257, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 257, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 258, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 258, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 258, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 258, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 259, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 259, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 259, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 259, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 260, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 260, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 260, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 260, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 261, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 261, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 261, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 261, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 262, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 262, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 262, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 262, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 263, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 263, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 263, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 263, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 264, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 264, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 264, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 264, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 265, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 265, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 265, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 265, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 268, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 268, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 268, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 268, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 269, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 269, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 269, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 269, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 270, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 270, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 270, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 270, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 271, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 271, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 271, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 271, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 272, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 272, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 272, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 272, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 273, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 273, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 273, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 273, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 274, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 274, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 274, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 274, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 275, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 275, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 275, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 275, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 276, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 276, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 276, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 276, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 277, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 277, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 277, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 277, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 278, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 278, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 278, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 278, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 279, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 279, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 279, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 279, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 280, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 280, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 280, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 280, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 281, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 281, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 281, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 281, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 282, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 282, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 282, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 282, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 283, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 283, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 283, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 283, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 284, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 284, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 284, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 284, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 285, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 285, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 285, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 285, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 286, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 286, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 286, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 286, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 287, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 287, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 287, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 287, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 290, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 290, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 290, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 290, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 291, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 291, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 291, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 291, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 292, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 292, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 292, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 292, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 293, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 293, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 293, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 293, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 294, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 294, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 294, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 294, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 295, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 295, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 295, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 295, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 296, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 296, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 296, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 296, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 297, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 297, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 297, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 297, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 298, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 298, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 298, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 298, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 299, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 299, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 299, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 299, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 300, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 300, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 300, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 300, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 301, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 301, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 301, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 301, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 302, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 302, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 302, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 302, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 303, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 303, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 303, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 303, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 304, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 304, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 304, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 304, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 305, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 305, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 305, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 305, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 306, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 306, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 306, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 306, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 307, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 307, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 307, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 307, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 308, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 308, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 308, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 308, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 309, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 309, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 309, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 309, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 312, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 312, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 312, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 312, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 313, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 313, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 313, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 313, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 314, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 314, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 314, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 314, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 315, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 315, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 315, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 315, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 316, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 316, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 316, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 316, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 317, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 317, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 317, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 317, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 318, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 318, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 318, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 318, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 319, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 319, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 319, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 319, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 320, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 320, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 320, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 320, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 321, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 321, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 321, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 321, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 322, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 322, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 322, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 322, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 323, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 323, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 323, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 323, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 324, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 324, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 324, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 324, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 325, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 325, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 325, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 325, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 326, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 326, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 326, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 326, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 327, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 327, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 327, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 327, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 328, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 328, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 328, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 328, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 329, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 329, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 329, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 329, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 330, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 330, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 330, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 330, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 331, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 331, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 331, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 331, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 334, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 334, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 334, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 334, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 335, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 335, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 335, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 335, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 336, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 336, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 336, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 336, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 337, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 337, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 337, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 337, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 338, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 338, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 338, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 338, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 339, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 339, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 339, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 339, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 340, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 340, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 340, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 340, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 341, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 341, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 341, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 341, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 342, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 342, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 342, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 342, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 343, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 343, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 343, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 343, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 344, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 344, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 344, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 344, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 345, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 345, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 345, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 345, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 346, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 346, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 346, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 346, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 347, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 347, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 347, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 347, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 348, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 348, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 348, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 348, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 349, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 349, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 349, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 349, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 350, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 350, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 350, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 350, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 351, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 351, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 351, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 351, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 352, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 352, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 352, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 352, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 353, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 353, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 353, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 353, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 356, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 356, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 356, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 356, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 357, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 357, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 357, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 357, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 358, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 358, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 358, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 358, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 359, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 359, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 359, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 359, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 360, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 360, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 360, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 360, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 361, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 361, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 361, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 361, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 362, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 362, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 362, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 362, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 363, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 363, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 363, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 363, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 364, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 364, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 364, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 364, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 365, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 365, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 365, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 365, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 366, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 366, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 366, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 366, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 367, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 367, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 367, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 367, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 368, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 368, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 368, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 368, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 369, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 369, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 369, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 369, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 370, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 370, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 370, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 370, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 371, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 371, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 371, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 371, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 372, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 372, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 372, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 372, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 373, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 373, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 373, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 373, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 374, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 374, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 374, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 374, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 375, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 375, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 375, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 375, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 378, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 378, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 378, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 378, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 379, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 379, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 379, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 379, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 380, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 380, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 380, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 380, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 381, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 381, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 381, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 381, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 382, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 382, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 382, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 382, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 383, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 383, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 383, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 383, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 384, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 384, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 384, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 384, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 385, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 385, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 385, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 385, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 386, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 386, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 386, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 386, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 387, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 387, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 387, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 387, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 388, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 388, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 388, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 388, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 389, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 389, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 389, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 389, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 390, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 390, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 390, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 390, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 391, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 391, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 391, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 391, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 392, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 392, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 392, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 392, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 393, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 393, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 393, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 393, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 394, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 394, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 394, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 394, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 395, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 395, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 395, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 395, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 396, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 396, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 396, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 396, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 397, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 397, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 397, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 397, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 400, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 400, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 400, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 400, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 401, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 401, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 401, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 401, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 402, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 402, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 402, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 402, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 403, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 403, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 403, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 403, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 404, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 404, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 404, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 404, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 405, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 405, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 405, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 405, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 406, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 406, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 406, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 406, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 407, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 407, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 407, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 407, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 408, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 408, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 408, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 408, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 409, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 409, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 409, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 409, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 410, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 410, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 410, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 410, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 411, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 411, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 411, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 411, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 412, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 412, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 412, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 412, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 413, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 413, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 413, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 413, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 414, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 414, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 414, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 414, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 415, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 415, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 415, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 415, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 416, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 416, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 416, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 416, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 417, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 417, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 417, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 417, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 418, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 418, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 418, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 418, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 419, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 419, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 419, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 419, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 422, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 422, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 422, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 422, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 423, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 423, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 423, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 423, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 424, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 424, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 424, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 424, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 425, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 425, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 425, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 425, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 426, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 426, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 426, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 426, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 427, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 427, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 427, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 427, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 428, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 428, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 428, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 428, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 429, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 429, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 429, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 429, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 430, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 430, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 430, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 430, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 431, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 431, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 431, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 431, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 432, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 432, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 432, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 432, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 433, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 433, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 433, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 433, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 434, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 434, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 434, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 434, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 435, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 435, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 435, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 435, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 436, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 436, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 436, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 436, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 437, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 437, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 437, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 437, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 438, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 438, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 438, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 438, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 439, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 439, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 439, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 439, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 440, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 440, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 440, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 440, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 441, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 441, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 441, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 441, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 444, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 444, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 444, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 444, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 445, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 445, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 445, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 445, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 446, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 446, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 446, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 446, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 447, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 447, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 447, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 447, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 448, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 448, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 448, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 448, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 449, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 449, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 449, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 449, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 450, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 450, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 450, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 450, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 451, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 451, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 451, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 451, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 452, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 452, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 452, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 452, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 453, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 453, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 453, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 453, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 454, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 454, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 454, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 454, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 455, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 455, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 455, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 455, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 456, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 456, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 456, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 456, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 457, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 457, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 457, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 457, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 458, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 458, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 458, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 458, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 459, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 459, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 459, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 459, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 460, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 460, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 460, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 460, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 461, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 461, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 461, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 461, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 462, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 462, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 462, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 462, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 463, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 463, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 463, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 463, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 466, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 466, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 466, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 466, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 467, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 467, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 467, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 467, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 468, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 468, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 468, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 468, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 469, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 469, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 469, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 469, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 470, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 470, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 470, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 470, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 471, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 471, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 471, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 471, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 472, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 472, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 472, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 472, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 473, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 473, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 473, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 473, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 474, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 474, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 474, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 474, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 475, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 475, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 475, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 475, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 476, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 476, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 476, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 476, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 477, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 477, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 477, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 477, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 478, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 478, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 478, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 478, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 479, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 479, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 479, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 479, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 480, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 480, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 480, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 480, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 481, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 481, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 481, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 481, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 482, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 482, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 482, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 482, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 483, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 483, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 483, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 483, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 484, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 484, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 484, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 484, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 485, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 485, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 485, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 485, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 488, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 488, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 488, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 488, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 489, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 489, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 489, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 489, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 490, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 490, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 490, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 490, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 491, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 491, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 491, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 491, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 492, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 492, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 492, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 492, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 493, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 493, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 493, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 493, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 494, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 494, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 494, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 494, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 495, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 495, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 495, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 495, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 496, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 496, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 496, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 496, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 497, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 497, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 497, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 497, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 498, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 498, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 498, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 498, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 499, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 499, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 499, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 499, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 500, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 500, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 500, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 500, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 501, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 501, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 501, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 501, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 502, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 502, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 502, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 502, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 503, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 503, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 503, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 503, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 504, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 504, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 504, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 504, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 505, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 505, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 505, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 505, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 506, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 506, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 506, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 506, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 507, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 507, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 507, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 507, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 510, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 510, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 510, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 510, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 511, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 511, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 511, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 511, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 512, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 512, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 512, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 512, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 513, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 513, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 513, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 513, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 514, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 514, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 514, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 514, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 515, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 515, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 515, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 515, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 516, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 516, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 516, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 516, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 517, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 517, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 517, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 517, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 518, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 518, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 518, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 518, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 519, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 519, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 519, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 519, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 520, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 520, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 520, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 520, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 521, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 521, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 521, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 521, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
cruncher = SequenceMatcher(self.charjunk)
eqi, eqj = None, None # 1st indices of equal lines (if any)
# search for the pair that matches best without being identical
# (identical lines must be junk lines, & we don't want to synch up
# on junk -- unless we have to)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
if eqi is None:
eqi, eqj = i, j
continue
cruncher.set_seq1(ai)
# computing similarity is expensive, so use the quick
# upper bounds first -- have seen this speed up messy
# compares by a factor of 3.
# note that ratio() is only expensive to compute the first
# time it's called on a sequence pair; the expensive part
# of the computation is cached by cruncher
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
if best_ratio < cutoff:
# no non-identical "pretty close" pair
if eqi is None:
# no identical pair either -- treat it as a straight replace
yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
return
# no close pair, but an identical pair -- synch up on that
best_i, best_j, best_ratio = eqi, eqj, 1.0
else:
# there's a close pair, so forget the identical pair (if any)
eqi = None
# a[best_i] very similar to b[best_j]; eqi is None iff they're not
# identical
# pump out diffs from before the synch point
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
# do intraline marking on the synch pair
aelt, belt = a[best_i], b[best_j]
if eqi is None:
# pump out a '-', '?', '+', '?' quad for the synched lines
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
else:
# the synch pair is identical
yield ' ' + aelt
# pump out diffs from after the synch point
> yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
C:\Python3x\Lib\difflib.py:985:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 522, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 522, bhi = 1101
def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
g = []
if alo < ahi:
if blo < bhi:
g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
else:
g = self._dump('-', a, alo, ahi)
elif blo < bhi:
g = self._dump('+', b, blo, bhi)
> yield from g
C:\Python3x\Lib\difflib.py:997:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
alo = 522, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
blo = 522, bhi = 1101
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
r"""
When replacing one block of lines with another, search the blocks
for *similar* lines; the best-matching pair (if any) is used as a
synch point, and intraline difference marking is done on the
similar pair. Lots of work, but often worth it.
Example:
>>> d = Differ()
>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
... ['abcdefGhijkl\n'], 0, 1)
>>> print(''.join(results), end="")
- abcDefghiJkl
+ abcdefGhijkl
"""
# don't synch up unless the lines have a similarity score of at
# least cutoff; best_ratio tracks the best score seen so far
best_ratio, cutoff = 0.74, 0.75
> cruncher = SequenceMatcher(self.charjunk)
C:\Python3x\Lib\difflib.py:915:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.SequenceMatcher pytest object at [hex]>
isjunk = <function IS_CHARACTER_JUNK at 0x000002A86576DC60>, a = '', b = ''
autojunk = True
def __init__(self, isjunk=None, a='', b='', autojunk=True):
"""Construct a SequenceMatcher.
Optional arg isjunk is None (the default), or a one-argument
function that takes a sequence element and returns true iff the
element is junk. None is equivalent to passing "lambda x: 0", i.e.
no elements are considered to be junk. For example, pass
lambda x: x in " \\t"
if you're comparing lines as sequences of characters, and don't
want to synch up on blanks or hard tabs.
Optional arg a is the first of two sequences to be compared. By
default, an empty string. The elements of a must be hashable. See
also .set_seqs() and .set_seq1().
Optional arg b is the second of two sequences to be compared. By
default, an empty string. The elements of b must be hashable. See
also .set_seqs() and .set_seq2().
Optional arg autojunk should be set to False to disable the
"automatic junk heuristic" that treats popular elements as junk
(see module documentation for more information).
"""
# Members:
# a
# first sequence
# b
# second sequence; differences are computed as "what do
# we need to do to 'a' to change it into 'b'?"
# b2j
# for x in b, b2j[x] is a list of the indices (into b)
# at which x appears; junk and popular elements do not appear
# fullbcount
# for x in b, fullbcount[x] == the number of times x
# appears in b; only materialized if really needed (used
# only for computing quick_ratio())
# matching_blocks
# a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
# ascending & non-overlapping in i and in j; terminated by
# a dummy (len(a), len(b), 0) sentinel
# opcodes
# a list of (tag, i1, i2, j1, j2) tuples, where tag is
# one of
# 'replace' a[i1:i2] should be replaced by b[j1:j2]
# 'delete' a[i1:i2] should be deleted
# 'insert' b[j1:j2] should be inserted
# 'equal' a[i1:i2] == b[j1:j2]
# isjunk
# a user-supplied function taking a sequence element and
# returning true iff the element is "junk" -- this has
# subtle but helpful effects on the algorithm, which I'll
# get around to writing up someday <0.9 wink>.
# DON'T USE! Only __chain_b uses this. Use "in self.bjunk".
# bjunk
# the items in b for which isjunk is True.
# bpopular
# nonjunk items in b treated as junk by the heuristic (if used).
self.isjunk = isjunk
self.a = self.b = None
self.autojunk = autojunk
> self.set_seqs(a, b)
C:\Python3x\Lib\difflib.py:182:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.SequenceMatcher pytest object at [hex]>, a = '', b = ''
def set_seqs(self, a, b):
"""Set the two sequences to be compared.
>>> s = SequenceMatcher()
>>> s.set_seqs("abcd", "bcde")
>>> s.ratio()
0.75
"""
self.set_seq1(a)
> self.set_seq2(b)
C:\Python3x\Lib\difflib.py:194:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.SequenceMatcher pytest object at [hex]>, b = ''
def set_seq2(self, b):
"""Set the second sequence to be compared.
The first sequence to be compared is not changed.
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75
>>> s.set_seq2("abcd")
>>> s.ratio()
1.0
>>>
SequenceMatcher computes and caches detailed information about the
second sequence, so if you want to compare one sequence S against
many sequences, use .set_seq2(S) once and call .set_seq1(x)
repeatedly for each of the other sequences.
See also set_seqs() and set_seq1().
"""
if b is self.b:
return
self.b = b
self.matching_blocks = self.opcodes = None
self.fullbcount = None
> self.__chain_b()
C:\Python3x\Lib\difflib.py:248:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <difflib.SequenceMatcher pytest object at [hex]>
def __chain_b(self):
# Because isjunk is a user-defined (not C) function, and we test
# for junk a LOT, it's important to minimize the number of calls.
# Before the tricks described here, __chain_b was by far the most
# time-consuming routine in the whole module! If anyone sees
# Jim Roskind, thank him again for profile.py -- I never would
# have guessed that.
# The first trick is to build b2j ignoring the possibility
# of junk. I.e., we don't call isjunk at all yet. Throwing
# out the junk later is much cheaper than building b2j "right"
# from the start.
b = self.b
self.b2j = b2j = {}
for i, elt in enumerate(b):
indices = b2j.setdefault(elt, [])
indices.append(i)
# Purge junk elements
self.bjunk = junk = set()
isjunk = self.isjunk
if isjunk:
> for elt in b2j.keys():
E RecursionError: maximum recursion depth exceeded while calling a Python object
C:\Python3x\Lib\difflib.py:288: RecursionError
|